<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">
  <link rel="manifest" href="/images/manifest.json">
  <meta name="msapplication-config" content="/images/browserconfig.xml">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/pace-js@1/themes/blue/pace-theme-minimal.css">
  <script src="//cdn.jsdelivr.net/npm/pace-js@1/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"daydaychen.github.io","root":"/","scheme":"Gemini","version":"7.7.2","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":true,"lazyload":true,"pangu":true,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":true,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":true,"preload":false},"motion":{"enable":true,"async":true,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="this is a desc.">
<meta property="og:type" content="website">
<meta property="og:title" content="宁静致远">
<meta property="og:url" content="daydaychen.github.io/index.html">
<meta property="og:site_name" content="宁静致远">
<meta property="og:description" content="this is a desc.">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="CT">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="daydaychen.github.io/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false
  };
</script>

  <title>宁静致远</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">宁静致远</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <p class="site-subtitle">this is a subtitle.</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocorrect="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result"></div>

</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/gitee%E6%8A%98%E8%85%BE%E8%AE%B0%E5%BD%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/gitee%E6%8A%98%E8%85%BE%E8%AE%B0%E5%BD%95/" class="post-title-link" itemprop="url">gitee折腾记录</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:17:18" itemprop="dateCreated datePublished" datetime="2020-03-06T14:17:18+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/gitee%E6%8A%98%E8%85%BE%E8%AE%B0%E5%BD%95/" class="post-meta-item leancloud_visitors" data-flag-title="gitee折腾记录" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="gitee-com-介绍"><a href="#gitee-com-介绍" class="headerlink" title="gitee.com 介绍"></a>gitee.com 介绍</h1><p>码云(gitee.com) 代码托管·协作开发平台，开发者近 400 万，托管项目超过 600 万，汇聚几乎所有本土原创开源项目，并于 2016 年推出企业版，提供企业级代码托管服务，成为开发领域领先的 SaaS 服务提供商。</p>
<h1 id="1-注册-gitee-com-账户"><a href="#1-注册-gitee-com-账户" class="headerlink" title="1. 注册 gitee.com 账户"></a>1. 注册 gitee.com 账户</h1><blockquote>
<p>打开 <a href="https://gitee.com/" target="_blank" rel="noopener">gitee官网</a>， 注册账号并登录</p>
</blockquote>
<h1 id="2-创建仓库"><a href="#2-创建仓库" class="headerlink" title="2. 创建仓库"></a>2. 创建仓库</h1><blockquote>
<p>创建仓库 <img data-src="https://pic.downk.cc/item/5e60e39498271cb2b8b33976.jpg" alt=""></p>
</blockquote>
<blockquote>
<p>键入仓库信息 <img data-src="https://pic.downk.cc/item/5e60e41598271cb2b8b378d9.jpg" alt=""></p>
</blockquote>
<ul>
<li>仓库名称：任意</li>
<li>归属/路径：保持默认即可</li>
<li>仓库介绍：非必填</li>
<li>是否开源：<ul>
<li>私有：拉取代码需要验证用户名和密码</li>
<li>公开：任何人无需验证身份即可直接拉取代码</li>
</ul>
</li>
<li>选择语言：项目代码的语言</li>
<li>添加.gitignore: 该文件用于指定上传代码时不包含项目内的某些文件，譬如包含密码的文件、缓存、项目环境、日志等无用文件，</li>
<li><input disabled="" type="checkbox"> 使用Readme 文件初始化这个仓库：用于介绍项目的文件，建议使用</li>
<li><input disabled="" type="checkbox"> 使用Issue 模板文件初始化这个仓库：初次配置可忽略</li>
<li><input disabled="" type="checkbox"> 使用Pull Request模板文件初始化这个仓库：初次配置可忽略</li>
<li>选择分支模型：初始化仓库时默认只有一个master分支，根据需要设定</li>
</ul>
<blockquote>
<p>点击<img data-src="https://pic.downk.cc/item/5e60e7c098271cb2b8b5272d.jpg" alt=""></p>
</blockquote>
<blockquote>
<p>仓库首页 <img data-src="https://pic.downk.cc/item/5e60e98198271cb2b8b60b38.jpg" alt=""></p>
</blockquote>
<h1 id="3-创建本地仓库-拉取远程仓库"><a href="#3-创建本地仓库-拉取远程仓库" class="headerlink" title="3. 创建本地仓库/拉取远程仓库"></a>3. 创建本地仓库/拉取远程仓库</h1><h2 id="3-1-创建本地仓库"><a href="#3-1-创建本地仓库" class="headerlink" title="3.1 创建本地仓库"></a>3.1 创建本地仓库</h2><blockquote>
<p>在bash环境下操作</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建目录并切换到该目录</span></span><br><span class="line">$ mkdir local_repo &amp;&amp; <span class="built_in">cd</span> local_repo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 初始化仓库</span></span><br><span class="line">$ git init</span><br></pre></td></tr></table></figure>

<h2 id="3-2-拉取远程仓库"><a href="#3-2-拉取远程仓库" class="headerlink" title="3.2 拉取远程仓库"></a>3.2 拉取远程仓库</h2><blockquote>
<p>获取远程仓库链接</p>
</blockquote>
<p><img data-src="https://pic.downk.cc/item/5e60ea9a98271cb2b8b6bf3b.jpg" alt=""></p>
<blockquote>
<p>拉取代码</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取远程仓库到本地目录learn_git</span></span><br><span class="line">$ git <span class="built_in">clone</span> https://gitee.com/daydaychen/learn_git.git learn_git</span><br><span class="line">Cloning into <span class="string">'learn_git'</span>...</span><br><span class="line">remote: Enumerating objects: 4, <span class="keyword">done</span>.</span><br><span class="line">remote: Counting objects: 100% (4/4), <span class="keyword">done</span>.</span><br><span class="line">remote: Compressing objects: 100% (4/4), <span class="keyword">done</span>.</span><br><span class="line">remote: Total 4 (delta 0), reused 0 (delta 0)</span><br><span class="line">Unpacking objects: 100% (4/4), <span class="keyword">done</span>.</span><br><span class="line">Checking connectivity... <span class="keyword">done</span>.</span><br></pre></td></tr></table></figure>

<h1 id="4-跟踪文件-取消跟踪"><a href="#4-跟踪文件-取消跟踪" class="headerlink" title="4. 跟踪文件/取消跟踪"></a>4. 跟踪文件/取消跟踪</h1><blockquote>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 当前目录下有两个文件</span></span><br><span class="line">dayday:learn_git$ ls</span><br><span class="line">total 8.0K</span><br><span class="line">-rw-rw-rw- 1 dayday dayday  953 Mar  5 20:06 README.en.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday 1.3K Mar  5 20:06 README.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 新建文件</span></span><br><span class="line">$ <span class="built_in">echo</span> <span class="string">"hello world"</span> &gt; day1_work.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看工作区状态</span></span><br><span class="line">dayday:learn_git$ git status</span><br><span class="line">On branch master</span><br><span class="line">Your branch is up-to-date with <span class="string">'origin/master'</span>.</span><br><span class="line">Untracked files: <span class="comment"># &lt;-- 有以下文件未跟踪</span></span><br><span class="line">  (use <span class="string">"git add &lt;file&gt;..."</span> to include <span class="keyword">in</span> what will be committed)</span><br><span class="line"></span><br><span class="line">        day1_work.md</span><br><span class="line"></span><br><span class="line">nothing added to commit but untracked files present (use <span class="string">"git add"</span> to track)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跟踪day1_work.md</span></span><br><span class="line">$ git add day1_work.md</span><br><span class="line">On branch master</span><br><span class="line">Your branch is up-to-date with <span class="string">'origin/master'</span>.</span><br><span class="line">Changes to be committed: <span class="comment"># &lt;-- 有以下文件已修改未提交</span></span><br><span class="line">  (use <span class="string">"git reset HEAD &lt;file&gt;..."</span> to unstage)</span><br><span class="line">        new file:   day1_work.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提交修改</span></span><br><span class="line">dayday:learn_git$ git commit -m <span class="string">'first commit'</span></span><br><span class="line">[master b52affd] first commit</span><br><span class="line"> 1 file changed, 1 insertion(+)</span><br><span class="line"> create mode 100644 day1_work.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看工作区状态</span></span><br><span class="line">dayday:learn_git$ git status</span><br><span class="line">On branch master</span><br><span class="line">Your branch is ahead of <span class="string">'origin/master'</span> by 1 commit.</span><br><span class="line">(use <span class="string">"git push"</span> to publish your <span class="built_in">local</span> commits)</span><br><span class="line">nothing to commit, working directory clean</span><br></pre></td></tr></table></figure>

<h1 id="5-创建分支-切换分支-删除分支"><a href="#5-创建分支-切换分支-删除分支" class="headerlink" title="5. 创建分支/切换分支/删除分支"></a>5. 创建分支/切换分支/删除分支</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 列出所有分支</span></span><br><span class="line">dayday:learn_git$ git branch --list</span><br><span class="line">* master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建dev分支</span></span><br><span class="line">dayday:learn_git$ git branch dev</span><br><span class="line">dayday:learn_git$ git branch --list</span><br><span class="line">dev</span><br><span class="line">* master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 切换到dev分支</span></span><br><span class="line">dayday:learn_git$ git checkout dev</span><br><span class="line">Switched to branch <span class="string">'dev'</span></span><br><span class="line">dayday:learn_git$ git branch --list</span><br><span class="line">* dev</span><br><span class="line">master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 切换回master分支</span></span><br><span class="line">dayday:learn_git$ git checkout master</span><br><span class="line">Switched to branch <span class="string">'master'</span></span><br><span class="line">Your branch is ahead of <span class="string">'origin/master'</span> by 1 commit.</span><br><span class="line">(use <span class="string">"git push"</span> to publish your <span class="built_in">local</span> commits) </span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除dev分支</span></span><br><span class="line">dayday:learn_git$ git branch -d dev</span><br><span class="line">Deleted branch dev (was b52affd).</span><br></pre></td></tr></table></figure>
<h1 id="8-合并分支"><a href="#8-合并分支" class="headerlink" title="8. 合并分支"></a>8. 合并分支</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建dev分支并切换过去</span></span><br><span class="line">dayday:learn_git$ git checkout -b dev</span><br><span class="line">Switched to a new branch <span class="string">'dev'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 新建文件</span></span><br><span class="line">dayday:learn_git$ <span class="built_in">echo</span> <span class="string">"dev branch working..."</span> &gt; dev.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看dev分支工作区</span></span><br><span class="line">dayday:learn_git$ ls</span><br><span class="line">total 8.0K</span><br><span class="line">-rw-rw-rw- 1 dayday dayday  953 Mar  5 20:06 README.en.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday 1.3K Mar  5 20:06 README.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday   12 Mar  5 20:12 day1_work.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday   22 Mar  5 20:44 dev.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跟踪dev.md</span></span><br><span class="line">dayday:learn_git$ git add .</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提交更改</span></span><br><span class="line">dayday:learn_git$ git commit -m <span class="string">'add dev.md'</span></span><br><span class="line">[dev a6986a9] add dev.md</span><br><span class="line">1 file changed, 1 insertion(+)</span><br><span class="line">create mode 100644 dev.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 切换到master分支</span></span><br><span class="line">dayday:learn_git$ git checkout master</span><br><span class="line">Switched to branch <span class="string">'master'</span></span><br><span class="line">Your branch is ahead of <span class="string">'origin/master'</span> by 1 commit.</span><br><span class="line">(use <span class="string">"git push"</span> to publish your <span class="built_in">local</span> commits) </span><br><span class="line"></span><br><span class="line">dayday:learn_git$ git branch</span><br><span class="line">dev</span><br><span class="line">* master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看master分支工作区</span></span><br><span class="line">dayday:learn_git$ ls</span><br><span class="line">total 8.0K</span><br><span class="line">-rw-rw-rw- 1 dayday dayday  953 Mar  5 20:06 README.en.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday 1.3K Mar  5 20:06 README.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday   12 Mar  5 20:12 day1_work.md</span><br><span class="line"></span><br><span class="line"><span class="comment"># 比较master分支和dev分支的区别</span></span><br><span class="line">dayday:learn_git$ git diff master dev</span><br><span class="line">diff --git a/dev.md b/dev.md</span><br><span class="line">new file mode 100644</span><br><span class="line">index 0000000..c38f76b</span><br><span class="line">--- /dev/null</span><br><span class="line">+++ b/dev.md</span><br><span class="line">@@ -0,0 +1 @@</span><br><span class="line">+dev branch working...</span><br><span class="line"></span><br><span class="line"><span class="comment"># 合并dev分支到master分支</span></span><br><span class="line">dayday:learn_git$ git merge dev</span><br><span class="line">Updating b52affd..a6986a9 Fast-forward</span><br><span class="line">dev.md | 1 + 1 file changed, 1 insertion(+)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看master分支工作区</span></span><br><span class="line">create mode 100644 dev.mddayday:learn_git$ ls</span><br><span class="line">total 8.0K</span><br><span class="line">-rw-rw-rw- 1 dayday dayday  953 Mar  5 20:06 README.en.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday 1.3K Mar  5 20:06 README.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday   12 Mar  5 20:12 day1_work.md</span><br><span class="line">-rw-rw-rw- 1 dayday dayday   22 Mar  5 20:53 dev.md</span><br></pre></td></tr></table></figure>


<h1 id="11-推送的远程仓库"><a href="#11-推送的远程仓库" class="headerlink" title="11. 推送的远程仓库"></a>11. 推送的远程仓库</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看工作区状态</span></span><br><span class="line">dayday:learn_git$ git status</span><br><span class="line">On branch master</span><br><span class="line">Your branch is ahead of <span class="string">'origin/master'</span> by 2 commits.</span><br><span class="line">(use <span class="string">"git push"</span> to publish your <span class="built_in">local</span> commits)</span><br><span class="line">nothing to commit, working directory clean </span><br><span class="line"></span><br><span class="line"><span class="comment"># 推送到远程仓库</span></span><br><span class="line">dayday:learn_git$ git push origin master</span><br><span class="line">Username <span class="keyword">for</span> <span class="string">'https://gitee.com'</span>: daydaychen</span><br><span class="line">Password <span class="keyword">for</span> <span class="string">'https://daydaychen@gitee.com'</span>:</span><br><span class="line">Counting objects: 6, <span class="keyword">done</span>.</span><br><span class="line">Delta compression using up to 4 threads.</span><br><span class="line">Compressing objects: 100% (4/4), <span class="keyword">done</span>.</span><br><span class="line">Writing objects: 100% (6/6), 537 bytes | 0 bytes/s, <span class="keyword">done</span>.</span><br><span class="line">Total 6 (delta 1), reused 0 (delta 0)</span><br><span class="line">remote: Powered by GITEE.COM [GNK-3.8]</span><br><span class="line">To https://gitee.com/daydaychen/learn_git.git</span><br><span class="line">4618244..a6986a9  master -&gt; master</span><br></pre></td></tr></table></figure>

<h1 id="12-向一个项目贡献"><a href="#12-向一个项目贡献" class="headerlink" title="12 向一个项目贡献"></a>12 向一个项目贡献</h1><blockquote>
<p>fork 仓库</p>
</blockquote>
<blockquote>
<p>拉取远程仓库到本地</p>
</blockquote>
<blockquote>
<p>提交修改并推送到远程仓库</p>
</blockquote>
<blockquote>
<p>提交Pull Request</p>
</blockquote>
<h1 id="13-仓库设置说明"><a href="#13-仓库设置说明" class="headerlink" title="13 仓库设置说明"></a>13 仓库设置说明</h1><blockquote>
<p>仓库成员管理</p>
</blockquote>
<p>添加成员，按角色分配仓库的读写权限</p>
<blockquote>
<p>部署公钥管理</p>
</blockquote>
<p>该操作通过非对称加密密钥对对仓库进行访问验证，无需每次输入用户名密码</p>
<p><img data-src="https://pic.downk.cc/item/5e60fefc98271cb2b8c187aa.jpg" alt=""></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E6%A6%82%E8%BF%B0-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E6%A6%82%E8%BF%B0-over/" class="post-title-link" itemprop="url">计算机网络-概述</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:17:07" itemprop="dateCreated datePublished" datetime="2020-03-06T14:17:07+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E6%A6%82%E8%BF%B0-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-概述" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="计算机网络在信息时代的作用"><a href="#计算机网络在信息时代的作用" class="headerlink" title="计算机网络在信息时代的作用"></a>计算机网络在信息时代的作用</h3><ul>
<li><p>数字化、网络化、信息化，一个以网络为核心的信息时代</p>
</li>
<li><p>三大类网络：电信网路、有线电视网络、计算机网路，核心是计算机网络</p>
</li>
</ul>
<h3 id="互联网概述"><a href="#互联网概述" class="headerlink" title="互联网概述"></a>互联网概述</h3><ul>
<li><p>网络和互联网</p>
<ul>
<li><p>网络：由若干<strong>结点</strong>（node）和连接这些结点的<strong>链路</strong>（link）组成。</p>
</li>
<li><p>互联网：网络之间通过路由器互联起来，这就构成一个覆盖范围更大的计算机网路。这样的网络称为<strong>互联网</strong></p>
</li>
<li><p>互联网是“网络的网络”</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/network-of-networks.gif" alt=""></p>
</li>
</ul>
</li>
<li><p>Internet是从单个网络<strong>ARPANET</strong>发展过来的</p>
</li>
<li><p>ARPANET是美国国防部在1969创建的第一个分组交换网</p>
</li>
<li><p>1983年TCP/IP协议成为ARPANET上的标准协议</p>
</li>
</ul>
<h3 id="互联网的组成"><a href="#互联网的组成" class="headerlink" title="互联网的组成"></a>互联网的组成</h3><ul>
<li><p>资源子网、通信子网</p>
</li>
<li><p>端系统之间的通信方式：客户-服务器方式（C/S方式）、对等方式（P2P方式）</p>
</li>
<li><p>交换方式</p>
<ul>
<li><strong>电路交换</strong>：整个报文的比特流连续地从源点直达终点，好像在一个管道中传送<ul>
<li>若要连续传送大量的数据，且其传送时间远大于连接建立时间，则电路交换的传输速率较快。 </li>
<li>在通话的全部时间内，通话的两个用户始终占用端到端的通信</li>
</ul>
</li>
<li><strong>报文交换</strong>：整个报文先传送到相邻结点，全部存储下来后查找转发表，转发到下一个结点。</li>
<li><strong>分组交换</strong>：单个分组（整个报文的一部分）传送到相邻结点，存储下来后查找转发表，转发到下一个结点。<ul>
<li>报文交换和分组交换不需要预分配传输带宽，在传输突发数据时可提高整个网络的信道利用率。</li>
<li>由于分组的长度往往远小于整个报文的长度，因此分组交换比报文交换的时延小。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="计算机网络的类别"><a href="#计算机网络的类别" class="headerlink" title="计算机网络的类别"></a>计算机网络的类别</h3><ul>
<li><p>按照网络的作用范围进行分类</p>
<ul>
<li>广域网（WAN）</li>
<li>城域网（MAN）</li>
<li>局域网（LAN）</li>
<li>个人局域网（PAN）</li>
<li>无限个人局域网（WPAN）</li>
</ul>
</li>
<li><p>按照网络的使用者进行分类</p>
<ul>
<li>公用网（Public Network）</li>
<li>专用网（Private Network）</li>
</ul>
</li>
</ul>
<h3 id="计算机网络的性能指标"><a href="#计算机网络的性能指标" class="headerlink" title="计算机网络的性能指标"></a>计算机网络的性能指标</h3><ul>
<li><p>速率：数据的传送速率，也成数据率。单位：bit/s</p>
</li>
<li><p>带宽：单位时间内网络中的某信道所能通过的“最高数据率”。单位：bit/s</p>
</li>
<li><p>吞吐量：单位时间内通过某个网络的实际的数据量。有时吞吐量可用每秒传送的字节数或帧数来表示。</p>
</li>
<li><p>时延：指数据从网络的一端传送到另一端所需的时间。</p>
<ul>
<li><strong>总时延</strong>=发送时延+传播时延+处理时延+排队时延<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4b2ae78c-e254-44df-9e37-578e2f2bef52.jpg" alt=""><ul>
<li>发送时延：数据帧长度（bit）/发送速率（bit/s）</li>
<li>传播时延：信道长度（m）/电磁波在信道上的传播速率（m/s）</li>
<li>处理时延：从收到的分组中提取数据部分、进行差错检验或查找合适路由等需要花费一定的时间</li>
<li>排队时延：当某一时刻收到的分组数量大于路由器的处理速度，分组在进入路由器输入队列后排队等待所消耗的时间</li>
</ul>
</li>
</ul>
</li>
<li><p>时延带宽积=传播时延 X 带宽</p>
</li>
<li><p>往返时间RTT=发送时间+接收时间</p>
<ul>
<li>发送时间=接收时间=数据长度/发送速率。计算时需要统一单位</li>
<li>有效数据率=数据长度/（发送时间+RTT）</li>
</ul>
</li>
<li><p>利用率：包含信道利用率、网络利用率</p>
<ul>
<li>信道利用率：指某信道由百分之几的时间是被利用的（有数据通过），完全空闲的信道的利用率为零</li>
<li>网络利用率：指全网络的信道利用率的加权平均值。<ul>
<li>当网络的利用率达到其容量的1/2时，时延就要加倍。</li>
<li><strong>信道或网络的利用率过高会产生非常大的时延</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="网络协议的三要素：语法、语义、同步"><a href="#网络协议的三要素：语法、语义、同步" class="headerlink" title="网络协议的三要素：语法、语义、同步"></a>网络协议的三要素：语法、语义、同步</h4><h3 id="计算机网络体系结构"><a href="#计算机网络体系结构" class="headerlink" title="计算机网络体系结构"></a>计算机网络体系结构</h3><p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0fa6c237-a909-4e2a-a771-2c5485cd8ce0.png" alt="image"></p>
<ol>
<li><p>五层协议</p>
<ul>
<li><p><strong>应用层</strong>：为特定应用程序提供数据传输服务，例如 HTTP、DNS 等协议。数据单位为报文。</p>
</li>
<li><p><strong>传输层</strong>：为进程提供通用数据传输服务。由于应用层协议很多，定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议：传输控制协议 TCP，提供面向连接、可靠的数据传输服务，数据单位为报文段；用户数据报协议 UDP，提供无连接、尽最大努力的数据传输服务，数据单位为用户数据报。TCP 主要提供完整性服务，UDP 主要提供及时性服务。</p>
</li>
<li><p><strong>网络层</strong>：为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。</p>
</li>
<li><p><strong>数据链路层</strong>：网络层针对的还是主机之间的数据传输服务，而主机之间可以有很多链路，链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。</p>
</li>
<li><p><strong>物理层</strong>：考虑的是怎样在传输媒体上传输数据比特流，而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异，使数据链路层感觉不到这些差异。</p>
</li>
</ul>
</li>
<li><p>OSI</p>
<ul>
<li><p><strong>表示层</strong>：数据压缩、加密以及数据描述，这使得应用程序不必关心在各台主机中数据内部格式不同的问题。</p>
</li>
<li><p><strong>会话层</strong>：建立及管理会话。</p>
</li>
<li><p>五层协议没有表示层和会话层，而是将这些功能留给应用程序开发者处理。</p>
</li>
</ul>
</li>
<li><p>TCP/IP</p>
<ul>
<li><p>它只有四层，相当于五层协议中数据链路层和物理层合并为网络接口层。</p>
</li>
<li><p>TCP/IP 体系结构不严格遵循 OSI 分层概念，应用层可能会直接使用 IP 层或者网络接口层。</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48d79be8-085b-4862-8a9d-18402eb93b31.png" alt="image"></p>
</li>
</ul>
</li>
<li><p>数据在各层之间的传递过程</p>
<ul>
<li><p>在向下的过程中，需要添加下层协议所需要的首部或者尾部，而在向上的过程中不断拆开首部和尾部。</p>
</li>
<li><p>路由器只有下面三层协议，因为路由器位于网络核心中，不需要为进程或者应用程序提供服务，因此也就不需要传输层和应用层。</p>
</li>
</ul>
</li>
</ol>
<h3 id="实体、协议、服务和服务访问点之间的区别和关系"><a href="#实体、协议、服务和服务访问点之间的区别和关系" class="headerlink" title="实体、协议、服务和服务访问点之间的区别和关系"></a>实体、协议、服务和服务访问点之间的区别和关系</h3><ul>
<li><p>实体：任何可发送或接收信息的硬件或软件进程</p>
</li>
<li><p>协议：控制两个对等实体（或多个实体）进行通信的规则的集合</p>
</li>
<li><p>服务：在协议的控制下，两个对等实体间的通信使得本层能够向上一层提供服务。要实现本层协议，还需要使用下一层所提供的服务</p>
</li>
<li><p>服务提供点：在同一系统中相邻两层的实体进行交互的地方，通常称之为<strong>服务访问点SAP（Service Access Point）</strong></p>
</li>
</ul>
<h4 id="协议和服务的区别："><a href="#协议和服务的区别：" class="headerlink" title="协议和服务的区别："></a>协议和服务的区别：</h4><ul>
<li>协议的实现保证了能够向上一层提供服务。使用本层服务的实体只能看见服务而无法看见下面的协议。也就是说，下面的协议对上面的实体是透明的。</li>
<li>其次，协议是“水平的”，即协议是控制对等实体之间通信的规则。但服务是“垂直的”，即服务是由下层向上层通过层间接口提供的。</li>
<li>那些能够被高一层实体“看得见”的功能才能称之为“服务”。</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E4%BC%A0%E8%BE%93%E5%B1%82-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E4%BC%A0%E8%BE%93%E5%B1%82-over/" class="post-title-link" itemprop="url">计算机网络-传输层</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:17:03" itemprop="dateCreated datePublished" datetime="2020-03-06T14:17:03+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E4%BC%A0%E8%BE%93%E5%B1%82-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-传输层" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>网络层只把分组发送到目的主机，但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信，传输层向高层用户屏蔽了下面网络层的核心细节，使应用程序看起来像是在两个传输层实体之间有一条端到端的逻辑通信信道。</p>
<h3 id="UDP-和-TCP-特点"><a href="#UDP-和-TCP-特点" class="headerlink" title="UDP 和 TCP 特点"></a>UDP 和 TCP 特点</h3><ul>
<li>用户数据报协议 UDP（User Datagram Protocol）是无连接的，尽最大可能交付，没有拥塞控制，面向报文（对于应用程序传下来的报文不合并也不拆分，只是添加 UDP 首部），支持一对一、一对多、多对一和多对多的交互通信。</li>
<li>传输控制协议 TCP（Transmission Control Protocol）是面向连接的，提供可靠交付，有流量控制，拥塞控制，提供全双工通信，面向字节流（把应用层传下来的报文看成字节流，把字节流组织成大小不等的数据块），每一条 TCP 连接只能是点对点的（一对一）。</li>
</ul>
<h3 id="UDP-首部格式"><a href="#UDP-首部格式" class="headerlink" title="UDP 首部格式"></a>UDP 首部格式</h3><p><img data-src="https://ae01.alicdn.com/kf/HTB1E4TPdWWs3KVjSZFxq6yWUXXaO.jpg" alt=""></p>
<p>首部字段只有 8 个字节，包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。</p>
<h3 id="TCP-首部格式"><a href="#TCP-首部格式" class="headerlink" title="TCP 首部格式"></a>TCP 首部格式</h3><p><img data-src="https://ae01.alicdn.com/kf/HTB1w_LPdW1s3KVjSZFA760_ZXXa1.png" alt=""></p>
<ul>
<li><strong>序号</strong> ：用于对字节流进行编号，例如序号为 301，表示第一个字节的编号为 301，如果携带的数据长度为 100 字节，那么下一个报文段的序号应为 401。</li>
<li><strong>确认号</strong> ：期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段，序号为 501，携带的数据长度为 200 字节，因此 B 期望下一个报文段的序号为 701，B 发送给 A 的确认报文段中确认号就为 701。</li>
<li><strong>数据偏移</strong> ：指的是数据部分距离报文段起始处的偏移量，实际上指的是首部的长度。</li>
<li><strong>确认 ACK</strong> ：当 ACK=1 时确认号字段有效，否则无效。TCP 规定，在连接建立后所有传送的报文段都必须把 ACK 置 1。</li>
<li><strong>同步 SYN</strong> ：在连接建立时用来同步序号。当 SYN=1，ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接，则响应报文中 SYN=1，ACK=1。</li>
<li>*<em>终止 FIN *</em>：用来释放一个连接，当 FIN=1 时，表示此报文段的发送方的数据已发送完毕，并要求释放连接。</li>
<li><strong>窗口</strong> ：窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制，是因为接收方的数据缓存空间是有限的。</li>
</ul>
<h3 id="TCP-的三次握手"><a href="#TCP-的三次握手" class="headerlink" title="TCP 的三次握手"></a>TCP 的三次握手</h3><p><img data-src="https://ae01.alicdn.com/kf/HTB1w_LPdW1s3KVjSZFA760_ZXXa1.png" alt=""></p>
<p>假设 A 为客户端，B 为服务器端。</p>
<ul>
<li>首先 B 处于 LISTEN（监听）状态，等待客户的连接请求。</li>
<li>A 向 B 发送连接请求报文，SYN=1，ACK=0，选择一个初始的序号 x。</li>
<li>B 收到连接请求报文，如果同意建立连接，则向 A 发送连接确认报文，SYN=1，ACK=1，确认号为 x+1，同时也选择一个初始的序号 y。</li>
<li>A 收到 B 的连接确认报文后，还要向 B 发出确认，确认号为 y+1，序号为 x+1。</li>
<li>B 收到 A 的确认后，连接建立。</li>
</ul>
<h4 id="三次握手的原因"><a href="#三次握手的原因" class="headerlink" title="三次握手的原因"></a>三次握手的原因</h4><p>第三次握手是为了防止失效的连接请求到达服务器，让服务器错误打开连接。</p>
<p>客户端发送的连接请求如果在网络中滞留，那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后，就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器，如果不进行三次握手，那么服务器就会打开两个连接。如果有第三次握手，客户端会忽略服务器之后发送的对滞留连接请求的连接确认，不进行第三次握手，因此就不会再次打开连接。</p>
<h3 id="TCP-的四次挥手"><a href="#TCP-的四次挥手" class="headerlink" title="TCP 的四次挥手"></a>TCP 的四次挥手</h3><p><img data-src="https://ae01.alicdn.com/kf/HTB11G2Id9SD3KVjSZFK76210VXa1.png" alt=""></p>
<p>以下描述不讨论序号和确认号，因为序号和确认号的规则比较简单。并且不讨论 ACK，因为 ACK 在连接建立之后都为 1。</p>
<ul>
<li>A 发送连接释放报文，FIN=1。</li>
<li>B 收到之后发出确认，此时 TCP 属于半关闭状态，B 能向 A 发送数据但是 A 不能向 B 发送数据。当 B 不再需要连接时，发送连接释放报文，FIN=1。</li>
<li>A 收到后发出确认，进入 TIME-WAIT 状态，等待 2 MSL（最大报文存活时间）后释放连接。</li>
<li>B 收到 A 的确认后释放连接。</li>
</ul>
<h4 id="四次挥手的原因"><a href="#四次挥手的原因" class="headerlink" title="四次挥手的原因"></a>四次挥手的原因</h4><p>客户端发送了 FIN 连接释放报文之后，服务器收到了这个报文，就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据，传送完毕之后，服务器会发送 FIN 连接释放报文。</p>
<h5 id="TIME-WAIT"><a href="#TIME-WAIT" class="headerlink" title="TIME_WAIT"></a>TIME_WAIT</h5><p>客户端收到服务器端的 FIN 豹纹后进入此状态，此时并不是直接进入CLOSED状态，还需要等待一个时间计时器设置的时间2MSL。这么做有两个理由：</p>
<ul>
<li>确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文， 那么就会重新发送连接释放请求报文， A 等待一段时间就是为了处理这种情况的发生。</li>
<li>等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失，使得下一个新的连接不会出现旧的连接请求报文。</li>
</ul>
<h3 id="TCP-可靠传输"><a href="#TCP-可靠传输" class="headerlink" title="TCP 可靠传输"></a>TCP 可靠传输</h3><p>TCP 使用超时重传来实现可靠传输：如果一个已经发送的报文段在超时时间内没有收到确认，那么就重传这个报文段。 </p>
<p>一个报文段从发送再到接收到确认所经过的时间称为往返时间 RTT，加权平均往返时间 RTTs 计算如下：</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB11vzRdW1s3KVjSZFA5jX_ZXXal.gif" alt=""></p>
<p>其中，0 ≤ a ＜ 1，RTTs 随着 a 的增加更容易受到 RTT 的影响。<br>超时时间 RTO 应该略大于 RTTs，TCP 使用的超时时间计算如下：</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1HSwVbfBj_uVjSZFp5jc0SXXaR.gif" alt=""></p>
<p>其中 RTTd 为偏差的加权平均值。</p>
<h3 id="TCP-滑动窗口"><a href="#TCP-滑动窗口" class="headerlink" title="TCP 滑动窗口"></a>TCP 滑动窗口</h3><p>窗口是缓存的一部分，用来暂时存放字节流。发送方和接收方各有一个窗口，接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小，发送方根据这个值和其它信息设置自己的窗口大小。</p>
<p>发送窗口内的字节都允许被发送，接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认，那么就将发送窗口向右滑动一定距离，直到左部第一个字节不是已发送并且已确认的状态；接收窗口的滑动类似，接收窗口左部字节已经发送确认并交付主机，就向右滑动接收窗口。</p>
<p>接收窗口只会对窗口内最后一个按序到达的字节进行确认，例如接收窗口已经收到的字节为 {31, 34, 35}，其中 {31} 按序到达，而 {34, 35} 就不是，因此只对字节 31 进行确认。发送方得到一个字节的确认之后，就知道这个字节之前的所有字节都已经被接收。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1FXrPd8Kw3KVjSZFOq6yrDVXaY.jpg" alt=""></p>
<h3 id="TCP-流量控制"><a href="#TCP-流量控制" class="headerlink" title="TCP 流量控制"></a>TCP 流量控制</h3><p>流量控制是为了控制发送方发送速率，保证接收方来得及接收。</p>
<p>接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小，从而影响发送方的发送速率。将窗口字段设置为 0 ，则发送方不能发送数据。</p>
<h3 id="TCP-拥塞控制"><a href="#TCP-拥塞控制" class="headerlink" title="TCP 拥塞控制"></a>TCP 拥塞控制</h3><p>如果网络出现拥塞，分组将会丢失，此时发送方会继续重传，从而导致网络拥塞程度更高。因此当出现拥塞时，应当控制发送方的速率。这一点和流量控制很像，但出发点不同。流量控制是为了让接收方能来得及接收，而拥塞控制是为了降低整个网络的拥塞程度。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB17THJd8iE3KVjSZFMq6zQhVXax.jpg" alt=""></p>
<p>TCP 主要通过四个算法来进行拥塞控制：慢开始、拥塞避免、快重传、快恢复。</p>
<p>发送方需要维护一个叫做拥塞窗口（cwnd）的状态变量，注意拥塞窗口与发送方窗口的区别：拥塞窗口只是一个状态变量，实际决定发送方能发送多少数据的是发送方窗口。</p>
<p>为了便于讨论，做如下假设：</p>
<ul>
<li>接收方有足够大的接收缓存，因此不会发生流量控制；</li>
<li>虽然 TCP 的窗口基于字节，但是这里设窗口的大小单位为报文段。</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1i5HKd9SD3KVjSZFK76210VXa1.png" alt=""></p>
<h4 id="1-慢开始与拥塞避免"><a href="#1-慢开始与拥塞避免" class="headerlink" title="1. 慢开始与拥塞避免"></a>1. 慢开始与拥塞避免</h4><p>发送的最初执行慢开始，令 cwnd = 1，发送方只能发送 1 个报文段；当收到确认后，将 cwnd 加倍，因此之后发送方能够发送的报文段数量为：2、4、8 …</p>
<p>注意到慢开始每个轮次都将 cwnd 加倍，这样会让 cwnd 增长速度非常快，从而使得发送方发送的速度增长速度过快，网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh，当 cwnd &gt;= ssthresh 时，进入拥塞避免，每个轮次只将 cwnd 加 1。</p>
<p>如果出现了超时，则令 ssthresh = cwnd / 2，然后重新执行慢开始。</p>
<h4 id="2-快重传与快恢复"><a href="#2-快重传与快恢复" class="headerlink" title="2. 快重传与快恢复"></a>2. 快重传与快恢复</h4><p>在接收方，要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2，此时收到 M4，应当发送对 M2 的确认。</p>
<p>在发送方，如果收到三个重复确认，那么可以知道下一个报文段丢失，此时执行快重传，立即重传下一个报文段。例如收到三个 M2，则 M3 丢失，立即重传 M3。</p>
<p>在这种情况下，只是丢失个别报文段，而不是网络拥塞。因此执行快恢复，令 ssthresh = cwnd / 2 ，cwnd = ssthresh，注意到此时直接进入拥塞避免。</p>
<p>慢开始和快恢复的快慢指的是 cwnd 的设定值，而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1，而快恢复 cwnd 设定为 ssthresh。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1XVrLd21G3KVjSZFk761K4XXak.png" alt=""></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82-over/" class="post-title-link" itemprop="url">计算机网络-数据链路层</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:16:59" itemprop="dateCreated datePublished" datetime="2020-03-06T14:16:59+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-数据链路层" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="基本问题"><a href="#基本问题" class="headerlink" title="基本问题"></a>基本问题</h3><h4 id="1-封装成帧"><a href="#1-封装成帧" class="headerlink" title="1. 封装成帧"></a>1. 封装成帧</h4><p>将网络层传下来的分组添加首部和尾部，用于标记帧的开始和结束。<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/29a14735-e154-4f60-9a04-c9628e5d09f4.png" alt="image"></p>
<h4 id="2-透明传输"><a href="#2-透明传输" class="headerlink" title="2. 透明传输"></a>2. 透明传输</h4><p>透明表示一个实际存在的事物看起来好像不存在一样。</p>
<p>帧使用首部和尾部进行定界，如果帧的数据部分含有和首尾部相同的内容，那么帧的开始和结束位置就会被错误的判定。因此需要在数据部分出现首尾部相同的内容前面插入转义字符。如果数据部分出现转义字符，那么就在转义字符前面再加个转义字符。在接收端进行处理之后可以还原出原始数据。这个过程透明传输的内容是转义字符，用户察觉不到转义字符的存在。</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e738a3d2-f42e-4755-ae13-ca23497e7a97.png" alt="image"></p>
<h4 id="3-差错检测"><a href="#3-差错检测" class="headerlink" title="3. 差错检测"></a>3. 差错检测</h4><p>目前数据链路层广泛使用来循环冗余校验（CRC）来检查比特差错。</p>
<h3 id="信道分类"><a href="#信道分类" class="headerlink" title="信道分类"></a>信道分类</h3><ul>
<li>点对点信道：一对一通信，因为不会发生碰撞，因此也比较简单，使用PPP协议进行控制。</li>
<li>广播信道：一对多通信，一个节点发送的数据能够倍广播信道上所有的节点接收到。<ul>
<li>所有的节点都在同一个广播信道上发送数据，因此需要有专门的控制方法进行协调，避免发生冲突（冲突也叫碰撞）。</li>
<li>主要有两种控制方法进行协调，一个是信道复用技术，另一个是CSMA/CD协议。</li>
</ul>
</li>
</ul>
<h4 id="点对点信道的相关概念"><a href="#点对点信道的相关概念" class="headerlink" title="点对点信道的相关概念"></a>点对点信道的相关概念</h4><ul>
<li>链路：从一个结点到相邻结点的一段物理线路（有线或无线），而中间没有任何其他的交换结点。</li>
<li>数据链路：当需要在一条线路上传送数据时，除了必须有一条物理线路外，还必须有一些必要的通信协议来控制这些数据的传输。若把实现这些协议的硬件和软件加到链路上，就构成来数据链路。<ul>
<li>现在最常用的方法是使用网络适配器来实现这些协议。</li>
</ul>
</li>
</ul>
<h3 id="PPP协议"><a href="#PPP协议" class="headerlink" title="PPP协议"></a>PPP协议</h3><p>PPP（Point to Point Protocol）点对点协议</p>
<p>互联网用户通常需要连接到某个ISP之后才能接入到互联网，PPP协议是用户计算机和ISP进行通信时所使用的数据链路层协议。<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e1ab9f28-cb15-4178-84b2-98aad87f9bc8.jpg" alt="image"></p>
<p>PPP的帧格式：</p>
<ul>
<li>F 字段为帧的定界符 1字节</li>
<li>A 和 C 字段暂时没有意义 1字节</li>
<li>FCS 字段是使用CRC的检验序列 2字节</li>
<li>信息部分的长度不超过1500字节</li>
<li>协议字段：信息字段  2字节<ul>
<li>0x0021 ： IP数据报</li>
<li>0xC021 ： 链路控制协议LCP的数据</li>
<li>0x8021 ： 网络层的控制数据</li>
</ul>
</li>
</ul>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/759013d7-61d8-4509-897a-d75af598a236.png" alt="image"></p>
<h4 id="CRC校验手动计算示例"><a href="#CRC校验手动计算示例" class="headerlink" title="CRC校验手动计算示例"></a>CRC校验手动计算示例</h4><p>生成多项式:G(x)=x^4+x^3+1，要求出二进制序列10110011的CRC校验码。</p>
<ul>
<li><ol>
<li>G(x)=x^4+x^3+1,二进制比特串为11001;(有X的几次方，对应的2的几次方的位就是1)</li>
</ol>
</li>
<li><ol start="2">
<li>因为校验码4位，所以10110011后面再加4个0，得到101100110000，用“模2除法”(其实就是亦或^)即可得出结果；</li>
</ol>
</li>
<li><ol start="3">
<li>CRC^101100110000得到101100110100。发送到接收端；</li>
</ol>
</li>
<li><ol start="4">
<li>接收端收到101100110100后除以11001(以“模2除法”方式去除),余数为0则无差错；</li>
</ol>
</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1XMQkdG1s3KVjSZFAq6x_ZXXaw.jpg" alt="image"></p>
<h4 id="字节填充、零比特填充"><a href="#字节填充、零比特填充" class="headerlink" title="字节填充、零比特填充"></a>字节填充、零比特填充</h4><ul>
<li>字节填充：在发送端，当发现信息字段中出现与定界符相同的字符时，插入转义符，当信息字段中出现转义符时，在转义符前插入转义符。</li>
<li>零比特填充：在发送端，扫描整个信息字段，只要发现有5个连续的1，则立即填入一个0，确保信息字段不会出现6个连续1.</li>
</ul>
<h3 id="CSMA-CD协议"><a href="#CSMA-CD协议" class="headerlink" title="CSMA/CD协议"></a>CSMA/CD协议</h3><p>CSMA/CD（Carrier Sense Multiple Access with Collision Detection） 表示载波监听多点接入/碰撞检测</p>
<ul>
<li>多点接入：说明这是总线型网络，许多主机以多点的方式连接到总线上</li>
<li>载波监听：每个主机都必须不停地监听信道。在发送前，如果监听到信道正在使用，就必须等待。</li>
<li>碰撞检测：在发送中，如果检测到信道已有其他主机正在发送数据，就表示发生了碰撞。虽然每个主机在发送数据之前都已经监听到信道为空闲，但是由于电磁波的传播时延的存在，还是有可能会发生碰撞。</li>
</ul>
<blockquote>
<p>总结：先听后发、边听边发、冲突停发、随机重发。<br>显然使用CSMA/CD协议，不可能同时进行发送和接收（但必须边发送边监听信道），因此使用CSMA/CD协议的以太网只能进行半双工通信。</p>
</blockquote>
<p>记端到端的传播时延为τ，最先发送的站点最多经过2τ就可以知道是否发生了碰撞，称2τ为<strong>争用期</strong>。只有经过争用期之后还没有检测到碰撞，才能肯定这次发送不会发生碰撞。</p>
<p>当发生碰撞时，站点要停止发送，等待一段时间再发送。这个时间采用<strong>截断二进制指数退避算法</strong>来确定。从离散的整数集合{0，1，…，(2^k-1)}中随机取出一个数，记作r，然后取r倍的争用期作为重传等待时间。</p>
<p>整数集合中的参数k按下面的公式计算：k = Min[重传次数, 10]</p>
<p>当重传16次仍不能成功时，表明网络堵塞，则丢弃该帧，并向高层报告。</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/19d423e9-74f7-4c2b-9b97-55890e0d5193.png" alt=""></p>
<h3 id="MAC地址"><a href="#MAC地址" class="headerlink" title="MAC地址"></a>MAC地址</h3><p>MAC地址是链路层地址，长度为6字节（48位），用于唯一标识网络适配器（网卡）。</p>
<p>一台主机拥有多少个网络适配器就有多少个MAC地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器，因此就有两个MAC地址。</p>
<h3 id="局域网"><a href="#局域网" class="headerlink" title="局域网"></a>局域网</h3><p>局域网是一种典型的广播信道。  </p>
<h4 id="局域网的特点："><a href="#局域网的特点：" class="headerlink" title="局域网的特点："></a>局域网的特点：</h4><ul>
<li>网络为一个单位所拥有，且地理范围和站点数目均有限。</li>
<li>具有广播功能，局域网上的主机可共享连接在局域网上的各种硬件和软件资源。</li>
<li>便于系统的扩展和逐渐演变，各设备的位置可灵活调整和改变。</li>
<li>提高了系统的可靠性、可用性和生存性。</li>
</ul>
<h4 id="局域网的分类："><a href="#局域网的分类：" class="headerlink" title="局域网的分类："></a>局域网的分类：</h4><p>可按照网络拓扑进行分类：</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/807f4258-dba8-4c54-9c3c-a707c7ccffa2.jpg" alt=""></p>
<h3 id="以太网"><a href="#以太网" class="headerlink" title="以太网"></a>以太网</h3><p>以太网是一种星型拓扑结构局域网。</p>
<h4 id="以太网的两个标准"><a href="#以太网的两个标准" class="headerlink" title="以太网的两个标准"></a>以太网的两个标准</h4><ol>
<li>DEC公司、Intel公司、Xerox公司联合提出的DIX Ethernet V2标准，数据率10Mbit/s，使用曼彻斯特编码。</li>
<li>IEEE 802委员会提出的IEEE 802.3标准，数据率：10Mbit/s，使用差分曼彻斯特编码。</li>
</ol>
<p>IEEE 802委员会把局域网的数据链路层拆分成了<strong>逻辑链路控制LLC</strong>、<strong>媒体接入控制MAC</strong>两个子层。<br>因为TCP/IP协议经常使用的局域网协议是DIX Ethernet V2标准，因此802.3的LLC的作用已经消失了，之后厂商生产的适配器就仅装有MAC协议而没有LLC协议。</p>
<h4 id="以太网帧格式："><a href="#以太网帧格式：" class="headerlink" title="以太网帧格式："></a>以太网帧格式：</h4><ul>
<li>类型：标记上层使用的协议；</li>
<li>数据：长度在46-1500之间，如果太小则需要填充；</li>
<li>FCS：帧检验序列，使用的是CRC检验方法；</li>
</ul>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/164944d3-bbd2-4bb2-924b-e62199c51b90.png" alt=""></p>
<h3 id="交换机Switch"><a href="#交换机Switch" class="headerlink" title="交换机Switch"></a>交换机Switch</h3><p>交换机具有自学习能力，学习的是交换表的内容，交换表中存储这MAC地址到接口的映射。</p>
<p>正是由于这种自学习能力，因此交换机是一种即插即用设备，不需要网络管理员手动配置交换表内容。</p>
<p>下图中，交换机有4个接口，主机A向主机B发送数据帧时，交换机把主机A到接口1的映射写入交换表中。为了发送数据帧到B，先查交换表，此时没有主机B的表项，那么主机A就发送广播帧，主机C和主机D会丢弃该帧，主机B回应该帧向主机A发送数据包时，交换机查找交换表得到主机A映射的接口为1，就发送数据帧到接口1，同时交换机添加主机B到接口2的映射。</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a4444545-0d68-4015-9a3d-19209dc436b3.png" alt=""></p>
<h3 id="虚拟局域网VLAN"><a href="#虚拟局域网VLAN" class="headerlink" title="虚拟局域网VLAN"></a>虚拟局域网VLAN</h3><p>虚拟局域网只是给局域网用户提供的一种服务，而不是一种新型局域网。</p>
<p>虚拟局域网可以建立与物理位置无关的逻辑组，只有在同一个虚拟局域网中的成员才会收到链路层广播信息。</p>
<p>例如下图中 (A1, A2, A3, A4) 属于一个虚拟局域网，A1 发送的广播会被 A2、A3、A4 收到，而其它站点收不到。</p>
<p>使用 VLAN 干线连接来建立虚拟局域网，每台交换机上的一个特殊接口被设置为干线接口，以互连 VLAN 交换机。IEEE 定义了一种扩展的以太网帧格式 802.1Q，它在标准以太网帧上加进了 4 字节首部 VLAN 标签，用于表示该帧属于哪一个虚拟局域网。</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e98e9d20-206b-4533-bacf-3448d0096f38.png" alt=""></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E7%BD%91%E7%BB%9C%E5%B1%82-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E7%BD%91%E7%BB%9C%E5%B1%82-over/" class="post-title-link" itemprop="url">计算机网络-网络层</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:16:57" itemprop="dateCreated datePublished" datetime="2020-03-06T14:16:57+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E7%BD%91%E7%BB%9C%E5%B1%82-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-网络层" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><p>因为网络层是整个互联网的核心，因此应当让网络层尽可能简单。网络层向上只提供简单灵活的、无连接的、尽最大努力交互的数据报服务。</p>
<p>使用 IP 协议，可以把异构的物理网络连接起来，使得在网络层看起来好像是一个统一的网络。</p>
<p>IP （Internet Protocol）网际协议</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1Qhjjd2WG3KVjSZFP760aiXXae.png" alt="image"></p>
<p>与 IP 协议配套使用的还有三个协议：</p>
<ul>
<li>地址解析协议 ARP（Address Resolution Protocol）</li>
<li>网际控制报文协议 ICMP（Internet Control Message Protocol）</li>
<li>网际组管理协议 IGMP（Internet Group Management Protocol）</li>
</ul>
<h4 id="虚拟互联网络"><a href="#虚拟互联网络" class="headerlink" title="虚拟互联网络"></a>虚拟互联网络</h4><p>将网络互相连接起来要使用一些<strong>中间设备</strong>。根据中间设备所在的层次，分为：</p>
<ul>
<li>物理层：转发器</li>
<li>数据链路层：网桥、交换机</li>
<li>网络层：路由器</li>
<li>网络层以上：网关</li>
</ul>
<h3 id="IP数据报格式"><a href="#IP数据报格式" class="headerlink" title="IP数据报格式"></a>IP数据报格式</h3><p><img data-src="https://ae01.alicdn.com/kf/HTB1taLpd8Gw3KVjSZFwq6zQ2FXae.jpg" alt="image"></p>
<ul>
<li><strong>版本</strong> : 有 4（IPv4）和 6（IPv6）两个值；<br>— <strong>首部长度</strong> : 占 4 位，因此最大值为 15。值为 1 表示的是 1 个 32 位字的长度，也就是 4 字节。因为固定部分长度为 20 字节，因此该值最小为 5。如果可选字段的长度不是 4 字节的整数倍，就用尾部的填充部分来填充。</li>
<li><strong>区分服务</strong> : 用来获得更好的服务，一般情况下不使用。</li>
<li><strong>总长度</strong> : 包括首部长度和数据部分长度。</li>
<li><strong>生存时间</strong> ：TTL，它的存在是为了防止无法交付的数据报在互联网中不断兜圈子。以路由器跳数为单位，当 TTL 为 0 时就丢弃数据报。</li>
<li><strong>协议</strong> ：指出携带的数据应该上交给哪个协议进行处理，例如 ICMP、TCP、UDP 等。</li>
<li><strong>首部检验和</strong> ：因为数据报每经过一个路由器，都要重新计算检验和，因此检验和不包含数据部分可以减少计算的工作量。</li>
<li><strong>标识</strong> : 在数据报长度过长从而发生分片的情况下，相同数据报的不同分片具有相同的标识符。</li>
<li><strong>片偏移</strong> : 和标识符一起，用于发生分片的情况。片偏移的单位为 8 字节。</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1SVrmd.uF3KVjSZK9762VtXXai.png" alt="image"></p>
<h4 id="IP地址编址方式"><a href="#IP地址编址方式" class="headerlink" title="IP地址编址方式"></a>IP地址编址方式</h4><p>IP地址的编址方式经历来三个历史阶段：</p>
<ul>
<li>分类</li>
<li>子网划分</li>
<li>无分类编址CIDR</li>
</ul>
<h4 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h4><p>由两部分组成，网络号和主机号，其中不同分类具有不同的网络号长度，并且是固定的。</p>
<p>IP地址 ::={&lt;网络号&gt;,&lt;主机号&gt;}</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1lZHtdWWs3KVjSZFx761WUXXaw.png" alt=""></p>
<blockquote>
<pre><code>1. 同一个局域网中网络号必须相同  
2. 用交换机互连的网段仍是一个局域网    
3. 路由器用于连接两个不同的网段    
4. 当两个路由器直接相连时，在连线两端的接口处，可以分配也可以不分配IP地址。不分配的话叫做无编号网络或无名网络。</code></pre></blockquote>
<pre><code>路由表条目分类：  
1. 特定主机路由
2. 特定网络路由
3. 默认路由</code></pre><h4 id="子网划分"><a href="#子网划分" class="headerlink" title="子网划分"></a>子网划分</h4><p>通过在主机号字段中拿一部分作为子网号，把两级IP地址划分为三级IP地址。</p>
<p>IP地址 ::={&lt;网络号&gt;,&lt;子网号&gt;,&lt;主机号&gt;}</p>
<p>要使用子网，必须配置子网掩码。一个B类地址的默认子网掩码为255.255.0.0，如果B类地址的子网占两个比特，那么子网掩码为11111111 11111111 11000000 00000000，也就是255.255.192.0。</p>
<p>注意，外部网络看不到子网的存在。</p>
<h4 id="无分类编址CIDR"><a href="#无分类编址CIDR" class="headerlink" title="无分类编址CIDR"></a>无分类编址CIDR</h4><p>无分类编址 CIDR 消除了传统 A 类、B 类和 C 类地址以及划分子网的概念，使用网络前缀和主机号来对 IP 地址进行编码，网络前缀的长度可以根据需要变化。</p>
<p>IP 地址 ::= {&lt; 网络前缀号 &gt;, &lt; 主机号 &gt;}</p>
<p>CIDR 的记法上采用在 IP 地址后面加上网络前缀长度的方法，例如 128.14.35.7/20 表示前 20 位为网络前缀。</p>
<p>CIDR 的地址掩码可以继续称为子网掩码，子网掩码首 1 长度为网络前缀的长度。</p>
<p>一个 CIDR 地址块中有很多地址，一个 CIDR 表示的网络就可以表示原来的很多个网络，并且在路由表中只需要一个路由就可以代替原来的多个路由，减少了路由表项的数量。把这种通过使用网络前缀来减少路由表项的方式称为路由聚合，也称为 构成超网 。</p>
<p>在路由表中的项目由“网络前缀”和“下一跳地址”组成，在查找时可能会得到不止一个匹配结果，应当采用最长前缀匹配来确定应该匹配哪一个。</p>
<h3 id="地址解析协议ARP"><a href="#地址解析协议ARP" class="headerlink" title="地址解析协议ARP"></a>地址解析协议ARP</h3><p>网络层实现主机之间的通信，而链路层实现具体每段链路之间的通信。因此在通信过程中，IP数据报的源地址和目的地址始终不变，而 MAC 地址随着链路的改变而改变。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1f5jAdWWs3KVjSZFxq6yWUXXao.jpg" alt=""></p>
<p>ARP 实现由 IP 地址得到 MAC 地址。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1AWrtd75E3KVjSZFCq6zuzXXaO.jpg" alt=""></p>
<p>每个主机都有一个 ARP 高速缓存，里面有本局域网上的各主机和路由器的 IP 地址到 MAC 地址的映射表。</p>
<p>如果主机 A 知道主机 B 的 IP 地址，但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射，此时主机 A 通过广播的方式发送 ARP 请求分组，主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其 MAC 地址，随后主机 A 向其高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1z_Prd.GF3KVjSZFo762mpFXao.png" alt=""></p>
<h3 id="网际控制报文协议ICMP"><a href="#网际控制报文协议ICMP" class="headerlink" title="网际控制报文协议ICMP"></a>网际控制报文协议ICMP</h3><p>ICMP 是问了更有效地转发 IP 数据报和提高交付成功的机会。它封装在 IP 数据报中，但是不属于高层协议。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1swzCdYus3KVjSZKbq6xqkFXaZ.jpg" alt=""></p>
<p>ICMP 报文分为差错报告报文和询问报文。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1a7fzd8Gw3KVjSZFD760WEpXa0.png" alt=""></p>
<ol>
<li>Ping</li>
</ol>
<p>Ping 是 ICMP 的一个重要应用，主要用来测试两台主机之间的连通性。</p>
<p>Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文，目的主机收到之后会发送 Echo 回答报文。Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。</p>
<ol start="2">
<li>Traceroute</li>
</ol>
<p>Traceroute 是 ICMP 的另一个应用，用来跟踪一个分组从源点到终点的路径。</p>
<p>Traceroute 发送的 IP 数据报封装的是无法交付的 UDP 用户数据报，并由目的主机发送终点不可达差错报告报文。</p>
<ul>
<li>源主机向目的主机发送一连串的 IP 数据报。第一个数据报 P1 的生存时间 TTL 设置为 1，当 P1 到达路径上的第一个路由器 R1 时，R1 收下它并把 TTL 减 1，此时 TTL 等于 0，R1 就把 P1 丢弃，并向源主机发送一个 ICMP 时间超过差错报告报文；</li>
<li>源主机接着发送第二个数据报 P2，并把 TTL 设置为 2。P2 先到达 R1，R1 收下后把 TTL 减 1 再转发给 R2，R2 收下后也把 TTL 减 1，由于此时 TTL 等于 0，R2 就丢弃 P2，并向源主机发送一个 ICMP 时间超过差错报文。</li>
<li>不断执行这样的步骤，直到最后一个数据报刚刚到达目的主机，主机不转发数据报，也不把 TTL 值减 1。但是因为数据报封装的是无法交付的 UDP，因此目的主机要向源主机发送 ICMP 终点不可达差错报告报文。</li>
<li>之后源主机知道了到达目的主机所经过的路由器 IP 地址以及到达每个路由器的往返时间。</li>
</ul>
<h3 id="虚拟专用网VPN"><a href="#虚拟专用网VPN" class="headerlink" title="虚拟专用网VPN"></a>虚拟专用网VPN</h3><p>由于 IP 地址的紧缺，一个机构能申请到的 IP 地址数往往远小于本机构所拥有的主机数。并且一个机构并不需要把所有的主机接入到外部的互联网中，机构内的计算机可以使用仅在本机构有效的 IP 地址（专用地址）。</p>
<blockquote>
</blockquote>
<pre><code>有三个专用地址块：
- 10.0.0.0 ~ 10.255.255.255
- 172.16.0.0 ~ 172.31.255.255
- 192.168.0.0 ~ 192.168.255.255</code></pre><p>VPN 使用公用的互联网作为本机构各专用网之间的通信载体。专用指机构内的主机只与本机构内的其它主机通信；虚拟指好像是，而实际上并不是，它有经过公用的互联网。</p>
<p>下图中，场所 A 和 B 的通信经过互联网，如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信，IP 数据报的源地址是 10.1.0.1，目的地址是 10.2.0.3。数据报先发送到与互联网相连的路由器 R1，R1 对内部数据进行加密，然后重新加上数据报的首部，源地址是路由器 R1 的全球地址 125.1.2.3，目的地址是路由器 R2 的全球地址 194.4.5.6。路由器 R2 收到数据报后将数据部分进行解密，恢复原来的数据报，此时目的地址为 10.2.0.3，就交付给 Y。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1sZjtd.WF3KVjSZPhq6xclXXaI.jpg" alt=""></p>
<h3 id="网络地址转换NAT"><a href="#网络地址转换NAT" class="headerlink" title="网络地址转换NAT"></a>网络地址转换NAT</h3><p>专用网内部的主机使用本地 IP 地址又想和互联网上的主机通信时，可以使用 NAT 来将本地 IP 转换为全球 IP。</p>
<p>在以前，NAT 将本地 IP 和全球 IP 一一对应，这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网。为了更有效地利用全球 IP 地址，现在常用的 NAT 转换表把传输层的端口号也用上了，使得多个专用网内部的主机共用一个全球 IP 地址。使用端口号的 NAT 也叫做网络地址与端口转换 NAPT。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1vkbYaMFY.1VjSZFq761dbXXaM.png" alt=""></p>
<h3 id="路由器的结构"><a href="#路由器的结构" class="headerlink" title="路由器的结构"></a>路由器的结构</h3><p>路由器从功能上可以划分为：路由选择和分组转发。</p>
<p>分组转发结构由三个部分组成：交换结构、一组输入端口和一组输出端口。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1cR_sd3aH3KVjSZFjq6AFWpXaX.jpg" alt=""></p>
<h4 id="路由器分组转发流程"><a href="#路由器分组转发流程" class="headerlink" title="路由器分组转发流程"></a>路由器分组转发流程</h4><ul>
<li>从数据报的首部提取目的主机的 IP 地址 D，得到目的网络地址 N。</li>
<li>若 N 就是与此路由器直接相连的某个网络地址，则进行直接交付；</li>
<li>若路由表中有目的地址为 D 的特定主机路由，则把数据报传送给表中所指明的下一跳路由器；</li>
<li>若路由表中有到达网络 N 的路由，则把数据报传送给路由表中所指明的下一跳路由器；</li>
<li>若路由表中有一个默认路由，则把数据报传送给路由表中所指明的默认路由器；</li>
<li>报告转发分组出错。</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1xEMGbfBj_uVjSZFpq6A0SXXag.jpg" alt=""></p>
<h3 id="路由选择协议"><a href="#路由选择协议" class="headerlink" title="路由选择协议"></a>路由选择协议</h3><p>路由选择协议都是自适应的，能随着网络通信量和拓扑结构的变化而自适应地进行调整。</p>
<p>互联网可以划分为许多较小的自治系统 AS，一个 AS 可以使用一种和别的 AS 不同的路由选择协议。</p>
<p>可以把路由选择协议划分为两大类：</p>
<ul>
<li>自治系统内部的路由选择：RIP 和 OSPF</li>
<li>自治系统间的路由选择：BGP</li>
</ul>
<h4 id="内部网关协议-RIP"><a href="#内部网关协议-RIP" class="headerlink" title="内部网关协议 RIP"></a>内部网关协议 RIP</h4><p>RIP 是一种<strong>基于距离向量</strong>的路由选择协议。距离是指跳数，直接相连的路由器跳数为 1。跳数最多为 15，超过 15 表示不可达。</p>
<p>RIP 按固定的时间间隔仅和相邻路由器交换自己的路由表，经过若干次交换之后，所有路由器最终会知道到达本自治系统中任何一个网络的最短距离和下一跳路由器地址。</p>
<p>距离向量算法：</p>
<ul>
<li>对地址为 X 的相邻路由器发来的 RIP 报文，先修改报文中的所有项目，把下一跳字段中的地址改为 X，并把所有的距离字段加 1；</li>
<li>对修改后的 RIP 报文中的每一个项目，进行以下步骤：<ul>
<li>若原来的路由表中没有目的网络 N，则把该项目添加到路由表中；</li>
<li>否则：若下一跳路由器地址是 X，则把收到的项目替换原来路由表中的项目；否则：若收到的项目中的距离 d 小于路由表中的距离，则进行更新（例如原始路由表项为 Net2, 5, P，新表项为 Net2, 4, X，则更新）；否则什么也不做。</li>
</ul>
</li>
<li>若 3 分钟还没有收到相邻路由器的更新路由表，则把该相邻路由器标为不可达，即把距离置为 16。</li>
</ul>
<p>RIP 协议实现简单，开销小。但是 RIP 能使用的最大距离为 15，限制了网络的规模。并且当网络出现故障时，要经过比较长的时间才能将此消息传送到所有路由器。</p>
<h4 id="内部网关协议-OSPF"><a href="#内部网关协议-OSPF" class="headerlink" title="内部网关协议 OSPF"></a>内部网关协议 OSPF</h4><p>开放最短路径优先 OSPF，是为了克服 RIP 的缺点而开发出来的。</p>
<p>开放表示 OSPF 不受某一家厂商控制，而是公开发表的；最短路径优先表示使用了 Dijkstra 提出的最短路径算法 SPF。</p>
<p>OSPF 具有以下特点：</p>
<ul>
<li>向本自治系统中的所有路由器发送信息，这种方法是洪泛法。</li>
<li>发送的信息就是与相邻路由器的链路状态，链路状态包括与哪些路由器相连以及链路的度量，度量用费用、距离、时延、带宽等来表示。</li>
<li>只有当链路状态发生变化时，路由器才会发送信息。</li>
</ul>
<p>所有路由器都具有全网的拓扑结构图，并且是一致的。相比于 RIP，OSPF 的更新过程收敛的很快。</p>
<h4 id="外部网关协议-BGP"><a href="#外部网关协议-BGP" class="headerlink" title="外部网关协议 BGP"></a>外部网关协议 BGP</h4><p>BGP（Border Gateway Protocol，边界网关协议）</p>
<p>AS 之间的路由选择很困难，主要是由于：</p>
<ul>
<li>互联网规模很大；</li>
<li>各个 AS 内部使用不同的路由选择协议，无法准确定义路径的度量；</li>
<li>AS 之间的路由选择必须考虑有关的策略，比如有些 AS 不愿意让其它 AS 经过。<br>BGP 只能寻找一条比较好的路由，而不是最佳路由。</li>
</ul>
<p>每个 AS 都必须配置 BGP 发言人，通过在两个相邻 BGP 发言人之间建立 TCP 连接来交换路由信息。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1glTAd8Kw3KVjSZFO761rDVXa0.png" alt=""></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E7%89%A9%E7%90%86%E5%B1%82-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E7%89%A9%E7%90%86%E5%B1%82-over/" class="post-title-link" itemprop="url">计算机网络-物理层</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:16:54" itemprop="dateCreated datePublished" datetime="2020-03-06T14:16:54+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E7%89%A9%E7%90%86%E5%B1%82-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-物理层" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="物理层"><a href="#物理层" class="headerlink" title="物理层"></a>物理层</h3><h4 id="物理层的基本概念"><a href="#物理层的基本概念" class="headerlink" title="物理层的基本概念"></a>物理层的基本概念</h4><h5 id="物理层的主要作用"><a href="#物理层的主要作用" class="headerlink" title="物理层的主要作用"></a>物理层的主要作用</h5><ul>
<li>机器特性、电气特性、功能特性、过程特性</li>
</ul>
<h4 id="数据通信的基本知识"><a href="#数据通信的基本知识" class="headerlink" title="数据通信的基本知识"></a>数据通信的基本知识</h4><h5 id="消息、数据、信号之间的关系"><a href="#消息、数据、信号之间的关系" class="headerlink" title="消息、数据、信号之间的关系"></a>消息、数据、信号之间的关系</h5><ul>
<li>通信的目的是传送<strong>消息（message）</strong>，<strong>数据（data）</strong>是运送消息的实体，<strong>信号（signal）</strong>是数据的电气或电磁的表现</li>
</ul>
<h5 id="信号的分类"><a href="#信号的分类" class="headerlink" title="信号的分类"></a>信号的分类</h5><ul>
<li><p>模拟信号（连续信号）</p>
</li>
<li><p>数字信号（离散信号）<br>代表不同离散数值的基本波形就称为<strong>码元</strong></p>
</li>
</ul>
<h5 id="信道"><a href="#信道" class="headerlink" title="信道"></a>信道</h5><ul>
<li>一条通信线路往往包含一条发送信道和一条接收信道</li>
</ul>
<h5 id="通信方式"><a href="#通信方式" class="headerlink" title="通信方式"></a>通信方式</h5><p>根据信息在传输线上的传输方向，分为以下三种通信方式</p>
<ul>
<li>单工通信：单向传输</li>
<li>半双工通信：双向交替传输</li>
<li>全双工通信：双向同时传输</li>
</ul>
<h5 id="常用的编码方式"><a href="#常用的编码方式" class="headerlink" title="常用的编码方式"></a>常用的编码方式</h5><ul>
<li>不归零制:负电平代表0，正电平代表1。</li>
<li>归零制：</li>
<li>曼彻斯特编码：位周期中心的上跳变代表0，下跳变代表1</li>
<li>差分曼彻斯特编码：位中心始终有跳变，位开始边界处有跳变代表0，没有代表1</li>
</ul>
<h5 id="带通调制"><a href="#带通调制" class="headerlink" title="带通调制"></a>带通调制</h5><ul>
<li>基带信号：计算机输出的代表各种文字或图像文件的数字信号都属于基带信号</li>
</ul>
<p>基带信号往往包含由较多低频或直流成分，而许多信道并不能传输这种低频分量或直流分量，因此，需要对基带信号进行<strong>调制</strong></p>
<ul>
<li>基带调制：<strong>对基带信号的波形进行变换</strong>，使其能够与信道特性相适应，变换后的信号仍是基带信号，称为编码  </li>
<li>带通调制：对基带信号使用<strong>载波</strong>进行调制，把基带信号的频率范围搬移到较高的频段，并转换为模拟信号，称为带通信号。</li>
</ul>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c34f4503-f62c-4043-9dc6-3e03288657df.jpg" alt="image"></p>
<h6 id="基本的带通调制方法"><a href="#基本的带通调制方法" class="headerlink" title="基本的带通调制方法"></a>基本的带通调制方法</h6><ul>
<li>调幅（AM）：即载波的振幅随基带数字信号而变化</li>
<li>调频（FM）：即载波的频率随基带数字信号而变化</li>
<li>调相（PM）：即载波的初始相位随基带数字信号而变化</li>
</ul>
<h4 id="传输媒体"><a href="#传输媒体" class="headerlink" title="传输媒体"></a>传输媒体</h4><h5 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h5><ul>
<li>导引型传输媒体（有线）<ul>
<li>双绞线<ol>
<li>无屏蔽双绞线</li>
<li>屏蔽双绞线</li>
</ol>
</li>
<li>同轴电缆</li>
<li>光缆<ul>
<li>单模光纤</li>
<li>多模光纤</li>
</ul>
</li>
</ul>
</li>
<li>非导引型传输媒体（无线）<ul>
<li>主要采用无线电微波通信，频率范围：300MHz～300GHz（波长1m～1mm），主要使用2～40GHz范围<ul>
<li>微波通信分为：地面微波接力通信、卫星通信</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="信道复用技术"><a href="#信道复用技术" class="headerlink" title="信道复用技术"></a>信道复用技术</h4><h5 id="1-频分复用FDM（Frequency-Division-Multiplexing）"><a href="#1-频分复用FDM（Frequency-Division-Multiplexing）" class="headerlink" title="1.频分复用FDM（Frequency Division Multiplexing）"></a>1.频分复用FDM（Frequency Division Multiplexing）</h5><p>频分复用的所有主机在相同的时间占用不同的频率带宽资源。<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4aa5e057-bc57-4719-ab57-c6fbc861c505.png" alt="image"></p>
<h5 id="2-时分复用TDM（Time-DM）"><a href="#2-时分复用TDM（Time-DM）" class="headerlink" title="2.时分复用TDM（Time DM）"></a>2.时分复用TDM（Time DM）</h5><p>时分复用的所有主机在不同的时间占用相同的频率带宽资源<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/67582ade-d44a-46a6-8757-3c1296cc1ef9.png" alt="image"><br>使用频分使用和时分复用进行通信，在通信的过程中主机会一直占用一部分信道资源。但是由于计算机数据的突发性质，通信过程没必要一直占用信道资源而不让出给其他用户使用，因此这两种方式对信道的利用率都不高</p>
<h5 id="3-统计时分复用STDM（Statistic-TDM）"><a href="#3-统计时分复用STDM（Statistic-TDM）" class="headerlink" title="3.统计时分复用STDM（Statistic TDM）"></a>3.统计时分复用STDM（Statistic TDM）</h5><p>是对时分复用的一种改进，不固定每个用户在时分复用帧中的位置，只要有数据就集中起来组成统计时分复用帧然后发送。<br><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6283be2a-814a-4a10-84bf-9592533fe6bc.png" alt="image"></p>
<h5 id="4-波分复用WDM（Wavelength-DM）"><a href="#4-波分复用WDM（Wavelength-DM）" class="headerlink" title="4.波分复用WDM（Wavelength DM）"></a>4.波分复用WDM（Wavelength DM）</h5><p>光的频分复用，由于光的频率很高，因此习惯上用波长而不是频率来表示所使用的光载波。</p>
<h5 id="5-码分复用CDM（Code-DM）"><a href="#5-码分复用CDM（Code-DM）" class="headerlink" title="5.码分复用CDM（Code DM）"></a>5.码分复用CDM（Code DM）</h5><p>为每个用户分配m bit的码片，并且所有的码片正交，对于任意两个码片S和T有</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/308a02e9-3346-4251-8c41-bd5536dab491.png" alt="image"></p>
<p>为了讨论方便，取m=8，设码片S为00011011。在拥有该码片的用户发送比特1时就发送该码片，发送比特0时就发送该码片的反码11100100。</p>
<p>在计算时将00011011记作（-1 -1 -1 +1 +1 -1 +1 +1），就可以得到</p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6fda1dc7-5c74-49c1-bb79-237a77e43a43.png" alt="image"></p>
<p><img data-src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e325a903-f0b1-4fbd-82bf-88913dc2f290.png" alt="image"></p>
<p>其中S’ 为S 的反码。</p>
<p>利用上面的式子可以知道，当接收端使用码片S对接收到的数据进行内积运算时，结果为0的时其他用户发送的数据，结果为1的时用户发送的比特1，结果为-1的是用户发送的比特0。</p>
<p>码分复用需要发送的数据量为原先的m倍。</p>
<h4 id="数字传输系统"><a href="#数字传输系统" class="headerlink" title="数字传输系统"></a>数字传输系统</h4><p>由于历史原因，多路复用的速率体系有两个互不兼容的国际标准，北美和日本的T1速率（1.544Mbit/s），欧洲的E1速率（2.048Mbit/s）</p>
<p>ITU-T制定的SDH中，STM-1的传输速率为155.52 Mbit/s</p>
<h4 id="宽带接入技术"><a href="#宽带接入技术" class="headerlink" title="宽带接入技术"></a>宽带接入技术</h4><p>ADSL（Asymmetric Digital Subscriber Line）非对称数字用户线技术<br>是用数字技术对现有的模拟电话用户线进行改造，使其能够承载宽带数字业务。<br>虽然标准模拟电话信号的频带被限制在300～3400Hz范围内，但用户线本身实际可通过的信号频率却超过1MHz。<br>ADSL技术把0～4kHz低端频谱留给传统电话使用，而把原来没有被利用的高端频谱留给用户上网使用。<br>ADSL的下行带宽远远大于上行带宽，“非对称”这个名词就是这样得出来的。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E5%BA%94%E7%94%A8%E5%B1%82-over/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E5%BA%94%E7%94%A8%E5%B1%82-over/" class="post-title-link" itemprop="url">计算机网络-应用层</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:16:51" itemprop="dateCreated datePublished" datetime="2020-03-06T14:16:51+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E5%BA%94%E7%94%A8%E5%B1%82-over/" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络-应用层" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="域名系统DNS"><a href="#域名系统DNS" class="headerlink" title="域名系统DNS"></a>域名系统DNS</h3><p>DNS（Domain Name Protocol）<br>DNS 是一个分布式数据库，提供了主机名和 IP 地址之间相互转换的服务。这里的分布式数据库是指，每个站点只保留它自己的那部分数据。</p>
<p>域名具有层次结构，从上到下以此为：根域名、顶级域名、二级域名。</p>
<h4 id="域名服务器"><a href="#域名服务器" class="headerlink" title="域名服务器"></a>域名服务器</h4><p>根据其功能分为：根域名服务器、顶级域名服务器、权限域名服务器、本地域名服务器。<br>前三者用于提供DNS解析<strong>数据</strong>，本地域名服务器用于提供DNS解析<strong>服务</strong>。</p>
<p>主机向本地域名服务器查询一般采用<strong>递归查询</strong>，<br>本地域名服务器向根域名服务器的查询一般采用<strong>迭代查询</strong>。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1xaNxeliE3KVjSZFMq6zQhVXau.jpg" alt=""></p>
<p>DNS 可以使用 UDP 或 TCP 进行传输，使用的端口号都为 53。大多数情况下 DNS 使用UDP 进行传输，这就要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性。在两种情况下会使用 TCP 进行传输：</p>
<ul>
<li>如果返回的响应超过的 512 字节（UDP最大支持512字节的数据）</li>
<li>区域传送（区域传送是主域服务器向辅助域名服务器传送变化的那部分数据）</li>
</ul>
<h3 id="文件传送协议FTP"><a href="#文件传送协议FTP" class="headerlink" title="文件传送协议FTP"></a>文件传送协议FTP</h3><p>FTP（File Transfer Protocol）</p>
<p>FTP 使用的 TCP 进行连接，它需要两个连接来传送一个文件：</p>
<ul>
<li>控制连接：服务器打开端口号 21 等待客户端的连接，客户端主动建立连接后，使用这个连接将客户端的命令传送给服务器，并传送服务器的应答。</li>
<li>数据连接：用来传送一个文件数据。</li>
</ul>
<p>根据数据连接是否是服务器端主动建立，FTP 有主动和被动两种模式：</p>
<ul>
<li>主动模式：服务器端主动建立数据连接，其中服务器端的端口号为 20，客户端的端口号随机，但是必须大于 1024，因为 0~1023 是熟知端口号。</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1g8NDelKw3KVjSZFOq6yrDVXaP.jpg" alt=""></p>
<ul>
<li>被动模式：客户端主动建立数据连接，其中客户端的端口号由客户端自己指定，服务器端的端口号随机。</li>
</ul>
<p><img data-src="https://ae01.alicdn.com/kf/HTB149Vyel1D3KVjSZFyq6zuFpXa5.jpg" alt=""></p>
<p>主动模式要求客户端开放端口号给服务器端，需要去配置客户端的防火墙。被动模式只需要服务器端开放端口号即可，无需客户端配置防火墙。但是被动模式会导致服务器端的安全性减弱，因为开放了过多的端口号。</p>
<h3 id="简单文件传送协议TFTP"><a href="#简单文件传送协议TFTP" class="headerlink" title="简单文件传送协议TFTP"></a>简单文件传送协议TFTP</h3><p>TFTP（Trivial File Transfer Protocol）</p>
<p>主要用于手机端，使用客户服务器方式，但使用 UDP 协议进行通信，TFTP 只支持文件传输而不支持交互。<br>TFTP 没有庞大的命令集，没有列目录功能，也不能对用户进行身份鉴别。</p>
<h4 id="TFTP的主要优点："><a href="#TFTP的主要优点：" class="headerlink" title="TFTP的主要优点："></a>TFTP的主要优点：</h4><ol>
<li>TFTP 可用于 UDP 环境。</li>
<li>TFTP 代码所占的内存较小。</li>
<li>每次传送的数据报文中有 512 个字节数据，最后一次可不足 512 字节</li>
<li>数据报文按序编号，从 1 开始。</li>
<li>支持 ASCII 码或二进制传送。</li>
<li>可对文件进行读写。</li>
<li>很用很简单的首部。</li>
</ol>
<h3 id="动态主机配置协议DHCP"><a href="#动态主机配置协议DHCP" class="headerlink" title="动态主机配置协议DHCP"></a>动态主机配置协议DHCP</h3><p>DHCP（Dynamic Host Configuration Protocol）提供了即插即用的连网方式，用户不再需要手动配置 IP 地址等信息。</p>
<p>DHCP 配置的内容不仅是 IP 地址，还包括子网掩码、网关 IP 地址。</p>
<p>DHCP 工作过程：</p>
<ol>
<li>客户端发送 Discover 报文，该报文的目的地址为 255.255.255.255:67，源地址为 0.0.0.0:68，被放入 UDP 中，该报文被广播到同一个子网的所有主机上。如果客户端和 DHCP 服务器不在同一个子网，就需要使用中继代理。</li>
<li>DHCP 服务器收到 Discover 报文之后，发送 Offer 报文给客户端，该报文包含了客户端所需要的信息。因为客户端可能收到多个 DHCP 服务器提供的信息，因此客户端需要进行选择。</li>
<li>如果客户端选择了某个 DHCP 服务器提供的信息，那么就发送 Request 报文给该 DHCP 服务器。</li>
<li>DHCP 服务器发送 Ack 报文，表示客户端此时可以使用提供给它的信息。</li>
</ol>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1ysVxegaH3KVjSZFjq6AFWpXai.jpg" alt=""></p>
<h3 id="远程登录协议TELNET"><a href="#远程登录协议TELNET" class="headerlink" title="远程登录协议TELNET"></a>远程登录协议TELNET</h3><p>又称<strong>终端仿真协议</strong>。</p>
<p>TELNET 用于登陆到远程主机上，并且远程主机上的输出也会返回。</p>
<p>TELNET 可以适应许多计算机和操作系统的差异，例如不同操作系统的换行符定义。即所谓的<strong>网络虚拟终端NVT</strong>（Network Virtual Terminal）</p>
<h3 id="电子邮件协议"><a href="#电子邮件协议" class="headerlink" title="电子邮件协议"></a>电子邮件协议</h3><p>一个电子邮件系统由三部分组成：用户代理、邮件服务器、邮件协议。</p>
<p>邮件协议包含发送协议和读取协议，发送协议常用 SMTP，读取协议常用 POP3 和 IMAP。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1H.pHebus3KVjSZKb760qkFXaR.png" alt=""></p>
<h4 id="1-SMTP"><a href="#1-SMTP" class="headerlink" title="1.SMTP"></a>1.SMTP</h4><p>SMTP（Simple Mail Transfer Protocol）简单邮件传送协议</p>
<p>SMTP 只能发送 ASCII 码，而互联网邮件扩充 MIME 可以发送二进制文件。</p>
<p>MIME 并没有改动或者取代 SMTP，而是增加邮件主体的结构，定义了非 ASCII 码的编码规则。</p>
<p><img data-src="https://ae01.alicdn.com/kf/HTB1glCLbvBj_uVjSZFp7630SXXam.png" alt=""></p>
<h4 id="2-POP3"><a href="#2-POP3" class="headerlink" title="2. POP3"></a>2. POP3</h4><p>POP3（Post Office Protocol）邮局协议</p>
<p>POP3 的特点是只要用户从服务器上读取了邮件，就把该邮件删除。</p>
<h4 id="3-IMAP"><a href="#3-IMAP" class="headerlink" title="3. IMAP"></a>3. IMAP</h4><p>IMAP（Internet Message Access Protocol）网际报文存取协议</p>
<p>IAMP 协议中客户端和服务器上的邮件保持同步，如果不手动删除邮件，那么服务器上的邮件也不会被删除。IMAP 这种做法可以上用户随时随地去访问服务器上的邮件。</p>
<h4 id="电子邮件的地址格式"><a href="#电子邮件的地址格式" class="headerlink" title="电子邮件的地址格式"></a>电子邮件的地址格式</h4><p>用户名 @ 邮件服务器的域名<br>示例：<a href="mailto:xyz@abc.com">xyz@abc.com</a><br>xyz为用户名，abc.com为邮件服务器域名</p>
<h4 id="电子邮件的信息格式"><a href="#电子邮件的信息格式" class="headerlink" title="电子邮件的信息格式"></a>电子邮件的信息格式</h4><p>一个电子邮件分为<strong>信封</strong>和<strong>内容</strong>两大部分。</p>
<p>首部关键字：</p>
<ul>
<li>To：后跟一个或多个收件人邮件地址</li>
<li>Subject：邮件主题</li>
<li>Cc：抄送，收件人可以看到抄送人</li>
<li>Bcc：暗送，收件人不知情</li>
<li>From：发件人的电邮地址</li>
<li>Date：发新日期</li>
<li>Reply-To：对方回信地址</li>
</ul>
<h3 id="常用端口"><a href="#常用端口" class="headerlink" title="常用端口"></a>常用端口</h3><table>
<thead>
<tr>
<th>应用</th>
<th>应用层协议</th>
<th>端口号</th>
<th>传输层协议</th>
<th>备注</th>
</tr>
</thead>
<tbody><tr>
<td>域名解析</td>
<td>DNS</td>
<td>53</td>
<td>UDP/TCP</td>
<td>长度超过 512 字节时使用 TCP</td>
</tr>
<tr>
<td>动态主机配置协议</td>
<td>DHCP</td>
<td>67/68</td>
<td>UDP</td>
<td></td>
</tr>
<tr>
<td>简单网络管理协议</td>
<td>SNMP</td>
<td>161/162</td>
<td>UDP</td>
<td></td>
</tr>
<tr>
<td>文件传送协议</td>
<td>FTP</td>
<td>20/21</td>
<td>TCP</td>
<td>控制连接 21，数据连接 20</td>
</tr>
<tr>
<td>远程终端协议</td>
<td>TELNET</td>
<td>23</td>
<td>TCP</td>
<td></td>
</tr>
<tr>
<td>超文本传送协议</td>
<td>HTTP</td>
<td>80</td>
<td>TCP</td>
<td></td>
</tr>
<tr>
<td>简单邮件传送协议</td>
<td>SMTP</td>
<td>25</td>
<td>TCP</td>
<td></td>
</tr>
<tr>
<td>邮件读取协议</td>
<td>POP3</td>
<td>110</td>
<td>TCP</td>
<td></td>
</tr>
<tr>
<td>网际报文存取协议</td>
<td>IMAP</td>
<td>143</td>
<td>TCP</td>
<td></td>
</tr>
</tbody></table>
<h3 id="万维网WWW"><a href="#万维网WWW" class="headerlink" title="万维网WWW"></a>万维网WWW</h3><p>WWW（World Wide Web），英文简称Web。<br>万维网是一个大规模、联机式的信息储藏所。<br>万维网以客户服务器方式工作。    </p>
<h4 id="统一资源定位符URL"><a href="#统一资源定位符URL" class="headerlink" title="统一资源定位符URL"></a>统一资源定位符URL</h4><p>URL（Uniform Resource Locator）</p>
<p>格式：&lt;协议&gt;://&lt;主机&gt;:&lt;端口&gt;/&lt;路径&gt;</p>
<h3 id="Web-页面请求过程"><a href="#Web-页面请求过程" class="headerlink" title="Web 页面请求过程"></a>Web 页面请求过程</h3><h4 id="1-DHCP-配置主机信息"><a href="#1-DHCP-配置主机信息" class="headerlink" title="1. DHCP 配置主机信息"></a>1. DHCP 配置主机信息</h4><ul>
<li><p>假设主机最开始没有 IP 地址以及其它信息，那么就需要先使用 DHCP 来获取。</p>
</li>
<li><p>主机生成一个 DHCP 请求报文，并将这个报文放入具有目的端口 67 和源端口 68 的 UDP 报文段中。</p>
</li>
<li><p>该报文段则被放入在一个具有广播 IP 目的地址(255.255.255.255) 和源 IP 地址（0.0.0.0）的 IP 数据报中。</p>
</li>
<li><p>该数据报被放置在 MAC 帧中，该帧具有目的地址 FF:FF:FF:FF:FF:FF，将广播到与交换机连接的所有设备。</p>
</li>
<li><p>连接在交换机的 DHCP 服务器收到广播帧之后，不断地向上分解得到 IP 数据报、UDP 报文段、DHCP 请求报文，之后生成 DHCP ACK 报文，该报文包含以下信息：IP 地址、DNS 服务器的 IP 地址、默认网关路由器的 IP 地址和子网掩码。该报文被放入 UDP 报文段中，UDP 报文段有被放入 IP 数据报中，最后放入 MAC 帧中。</p>
</li>
<li><p>该帧的目的地址是请求主机的 MAC 地址，因为交换机具有自学习能力，之前主机发送了广播帧之后就记录了 MAC 地址到其转发接口的交换表项，因此现在交换机就可以直接知道应该向哪个接口发送该帧。</p>
</li>
<li><p>主机收到该帧后，不断分解得到 DHCP 报文。之后就配置它的 IP 地址、子网掩码和 DNS 服务器的 IP 地址，并在其 IP 转发表中安装默认网关。</p>
</li>
</ul>
<h4 id="2-ARP-解析-MAC-地址"><a href="#2-ARP-解析-MAC-地址" class="headerlink" title="2. ARP 解析 MAC 地址"></a>2. ARP 解析 MAC 地址</h4><ul>
<li><p>主机通过浏览器生成一个 TCP 套接字，套接字向 HTTP 服务器发送 HTTP 请求。为了生成该套接字，主机需要知道网站的域名对应的 IP 地址。</p>
</li>
<li><p>主机生成一个 DNS 查询报文，该报文具有 53 号端口，因为 DNS 服务器的端口号是 53。</p>
</li>
<li><p>该 DNS 查询报文被放入目的地址为 DNS 服务器 IP 地址的 IP 数据报中。</p>
</li>
<li><p>该 IP 数据报被放入一个以太网帧中，该帧将发送到网关路由器。</p>
</li>
<li><p>DHCP 过程只知道网关路由器的 IP 地址，为了获取网关路由器的 MAC 地址，需要使用 ARP 协议。</p>
</li>
<li><p>主机生成一个包含目的地址为网关路由器 IP 地址的 ARP 查询报文，将该 ARP 查询报文放入一个具有广播目的地址（FF:FF:FF:FF:FF:FF）的以太网帧中，并向交换机发送该以太网帧，交换机将该帧转发给所有的连接设备，包括网关路由器。</p>
</li>
<li><p>网关路由器接收到该帧后，不断向上分解得到 ARP 报文，发现其中的 IP 地址与其接口的 IP 地址匹配，因此就发送一个 ARP 回答报文，包含了它的 MAC 地址，发回给主机</p>
</li>
</ul>
<h4 id="3-DNS-解析域名"><a href="#3-DNS-解析域名" class="headerlink" title="3. DNS 解析域名"></a>3. DNS 解析域名</h4><ul>
<li><p>知道了网关路由器的 MAC 地址之后，就可以继续 DNS 的解析过程了。</p>
</li>
<li><p>网关路由器接收到包含 DNS 查询报文的以太网帧后，抽取出 IP 数据报，并根据转发表决定该 IP 数据报应该转发的路由器。</p>
</li>
<li><p>因为路由器具有内部网关协议（RIP、OSPF）和外部网关协议（BGP）这两种路由选择协议，因此路由表中已经配置了网关路由器到达 DNS 服务器的路由表项。</p>
</li>
<li><p>到达 DNS 服务器之后，DNS 服务器抽取出 DNS 查询报文，并在 DNS 数据库中查找待解析的域名。</p>
</li>
<li><p>找到 DNS 记录之后，发送 DNS 回答报文，将该回答报文放入 UDP 报文段中，然后放入 IP 数据报中，通过路由器反向转发回网关路由器，并经过以太网交换机到达主机。</p>
</li>
</ul>
<h4 id="4-HTTP-请求页面"><a href="#4-HTTP-请求页面" class="headerlink" title="4. HTTP 请求页面"></a>4. HTTP 请求页面</h4><ul>
<li><p>有了 HTTP 服务器的 IP 地址之后，主机就能够生成 TCP 套接字，该套接字将用于向 Web 服务器发送 HTTP GET 报文。</p>
</li>
<li><p>在生成 TCP 套接字之前，必须先与 HTTP 服务器进行三次握手来建立连接。生成一个具有目的端口 80 的 TCP SYN 报文段，并向 HTTP 服务器发送该报文段。</p>
</li>
<li><p>HTTP 服务器收到该报文段之后，生成 TCP SYN ACK 报文段，发回给主机。</p>
</li>
<li><p>连接建立之后，浏览器生成 HTTP GET 报文，并交付给 HTTP 服务器。</p>
</li>
<li><p>HTTP 服务器从 TCP 套接字读取 HTTP GET 报文，生成一个 HTTP 响应报文，将 Web 页面内容放入报文主体中，发回给主机。</p>
</li>
<li><p>浏览器收到 HTTP 响应报文后，抽取出 Web 页面内容，之后进行渲染，显示 Web 页面。</p>
</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/01-%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/01-%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/" class="post-title-link" itemprop="url">正则表达式</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:16:31" itemprop="dateCreated datePublished" datetime="2020-03-06T14:16:31+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/01-%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/" class="post-meta-item leancloud_visitors" data-flag-title="正则表达式" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><h4 id="re模块操作"><a href="#re模块操作" class="headerlink" title="re模块操作"></a>re模块操作</h4><ol>
<li>re模块的使用过程<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># 导入re模块</span><br><span class="line">import re</span><br><span class="line"></span><br><span class="line"># 使用match方法进行匹配操作</span><br><span class="line"># re.match(正则表达式，要匹配的字符串)</span><br><span class="line">result &#x3D; re.match(r&quot;[Hh]ello&quot;, &quot;hello world&quot;)</span><br><span class="line"></span><br><span class="line"># 如果上一步匹配到数据的话，可以使用group方法来提取数据</span><br><span class="line">result.group()</span><br><span class="line"></span><br><span class="line">result &#x3D; re.match(r&quot;[Hh]ello&quot;, &quot;hello world&quot;).group()   # 匹配后直接提取数据</span><br></pre></td></tr></table></figure></li>
<li>re模块示例<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">#coding&#x3D;utf-8</span><br><span class="line"></span><br><span class="line">import re</span><br><span class="line">result &#x3D; re.match(&quot;itcast&quot;, &quot;itcast.cn&quot;)</span><br><span class="line">result.group()</span><br></pre></td></tr></table></figure>
<h4 id="匹配单个字符"><a href="#匹配单个字符" class="headerlink" title="匹配单个字符"></a>匹配单个字符</h4>字符|功能|示例</li>
</ol>
<p>—|—|—<br>.  | 匹配任意1个字符(<strong>除了\n</strong>)<br>[] | 匹配[]中列举的字符 | [1-8] 匹配1到8；[16] 匹配1或6；[1-36-8] 匹配1到3 6到8<br>\d | 匹配一位数字，即0-9<br>\D | 匹配非数字，即不是数字<br>\s | 匹配空白，即空格，tab键<br>\S | 匹配非空白<br>\w | 匹配单词字符，即a-z、A-Z、0-9、_、各类语言字符。。。<br>\W | 匹配非单词字符</p>
<h4 id="匹配多个字符"><a href="#匹配多个字符" class="headerlink" title="匹配多个字符"></a>匹配多个字符</h4><table>
<thead>
<tr>
<th>字符</th>
<th>功能</th>
</tr>
</thead>
<tbody><tr>
<td>*</td>
<td>匹配前一个字符出现0次或无限次，即可有可无</td>
</tr>
<tr>
<td>+</td>
<td>匹配前一个字符出现1次或无限次，即至少1次</td>
</tr>
<tr>
<td>?</td>
<td>匹配前一个字符出现0次或1次，即要么没有，要么有1次</td>
</tr>
<tr>
<td>{m}</td>
<td>匹配前一个字符出现m次</td>
</tr>
<tr>
<td>{m, n}</td>
<td>匹配前一个字符出现从m到n次</td>
</tr>
</tbody></table>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># 匹配\d 1到3次</span><br><span class="line">re.match(r&quot;速度与激情\d&#123;1，3&#125;&quot;, &quot;速度与激情3&quot;).group()</span><br><span class="line"></span><br><span class="line"># 匹配连续十一位数字</span><br><span class="line">re.match(r&quot;\d&#123;11&#125;&quot;, &quot;12345678901&quot;).group()</span><br><span class="line"></span><br><span class="line"># 匹配手机号</span><br><span class="line">re.match(r&quot;\d&#123;3,4&#125;-?\d&#123;7,8&#125;&quot;,&quot;0310-3328839&quot;).group()</span><br><span class="line"></span><br><span class="line"># 匹配&#39;\n&#39;</span><br><span class="line">re.match(r&quot;.*&quot;, html_content, re.S).group()</span><br></pre></td></tr></table></figure>

<h4 id="匹配开头结尾"><a href="#匹配开头结尾" class="headerlink" title="匹配开头结尾"></a>匹配开头结尾</h4><table>
<thead>
<tr>
<th>字符</th>
<th>功能</th>
</tr>
</thead>
<tbody><tr>
<td>^</td>
<td>匹配字符串开头</td>
</tr>
<tr>
<td>$</td>
<td>匹配字符串结尾</td>
</tr>
</tbody></table>
<h4 id="匹配分组"><a href="#匹配分组" class="headerlink" title="匹配分组"></a>匹配分组</h4><table>
<thead>
<tr>
<th>字符</th>
<th>功能</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
</tr>
<tr>
<td>(ab)</td>
<td>将括号中字符作为一个分组</td>
</tr>
<tr>
<td>\num</td>
<td>引用分组num匹配到的字符串</td>
</tr>
<tr>
<td>(?P<name>)</td>
<td>分组起别名</td>
</tr>
<tr>
<td>(?P=name)</td>
<td>引用别名为name分组匹配到的字符串</td>
</tr>
<tr>
<td><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">re.match(r&quot;([a-zA-Z0-9_]&#123;4,20&#125;)@(163|126)\.com$&quot;,&quot;day@163.com&quot;).group(1)</span><br><span class="line">--&gt; &#39;day&#39;</span><br><span class="line">re.match(r&quot;([a-zA-Z0-9_]&#123;4,20&#125;)@(163|126)\.com$&quot;,&quot;day@163.com&quot;).group(2)</span><br><span class="line">--&gt; &#39;163&#39;</span><br></pre></td></tr></table></figure></td>
<td></td>
</tr>
</tbody></table>
<p><strong>示例</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">re.match(r&quot;&lt;(\w*)&gt;.*&lt;&#x2F;\1&gt;&quot;,&quot;&lt;h1&gt;hahaha&lt;&#x2F;h1&gt;&quot;).group()</span><br><span class="line"></span><br><span class="line">re.match(r&quot;&lt;(\w*)&gt;&lt;(\w*)&gt;.*&lt;&#x2F;\2&gt;&lt;&#x2F;\1&gt;&quot;,&quot;&lt;body&gt;&lt;h1&gt;hahaha&lt;&#x2F;h1&gt;&lt;body&gt;&quot;).group()</span><br><span class="line"></span><br><span class="line">re.match(r&quot;&lt;(?P&lt;p1&gt;\w*)&gt;.*&lt;&#x2F;?P&#x3D;p1&gt;&quot;,&quot;&lt;h1&gt;hahaha&lt;&#x2F;h1&gt;&quot;).group()</span><br></pre></td></tr></table></figure>

<h4 id="re模块的高级用法"><a href="#re模块的高级用法" class="headerlink" title="re模块的高级用法"></a>re模块的高级用法</h4><p><strong>search</strong></p>
<ol>
<li>search不从头开始匹配，只要匹配到相应值就结束</li>
<li>match默认从头开始匹配<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br><span class="line"></span><br><span class="line">ret &#x3D; re.search(r&quot;\d+&quot;,&quot;阅读次数为9999&quot;)</span><br><span class="line">ret.group()</span><br><span class="line">--&gt; &#39;9999&#39;</span><br></pre></td></tr></table></figure></li>
</ol>
<p><strong>findall</strong><br>findall从头开始匹配，提取所有符合要求的字符串<br>需求：统计出Python、C、C++相应文章阅读的次数</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br><span class="line"></span><br><span class="line">ret &#x3D; re.findall(r&quot;\d+&quot;,&quot;python &#x3D; 9999, c &#x3D; 7890, c++ &#x3D; 12345&quot;)</span><br><span class="line">print(ret)</span><br><span class="line">--&gt;[&#39;9999&#39;, &#39;7890&#39;, &#39;12345&#39;]</span><br></pre></td></tr></table></figure>

<p><strong>sub</strong><br>将匹配到的数据进行<strong>替换</strong><br>需求：将匹配到的阅读次数加1</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br><span class="line"></span><br><span class="line">def add(temp):</span><br><span class="line">    strNum &#x3D; temp.group()</span><br><span class="line">    num &#x3D; int(strNum) + 1</span><br><span class="line">    return str(num)</span><br><span class="line"></span><br><span class="line">ret &#x3D; re.sub(r&quot;\d+&quot;, add, &#39;python &#x3D; 997 c++ &#x3D; 900&#39;)</span><br><span class="line">print(ret)</span><br><span class="line">--&gt; &#39;python &#x3D; 998 c++ &#x3D; 901&#39;</span><br></pre></td></tr></table></figure>

<p><strong>split</strong><br>根据匹配进行切割字符串，并返回一个列表<br>需求：切割字符串“info:xiaoZhang 33 shandong”</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import re</span><br><span class="line"></span><br><span class="line">ret &#x3D; re.split(r&quot;:| &quot;, &quot;info:xiaoZhang 33 shandong&quot;)</span><br><span class="line">print(ret)</span><br><span class="line">--&gt; [&#39;info&#39;, &#39;xiaoZhang&#39;, &#39;33&#39;, &#39;shandong&#39;]</span><br></pre></td></tr></table></figure>

<h4 id="贪婪和非贪婪"><a href="#贪婪和非贪婪" class="headerlink" title="贪婪和非贪婪"></a>贪婪和非贪婪</h4><h4 id="r的作用"><a href="#r的作用" class="headerlink" title="r的作用"></a>r的作用</h4>
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E8%BF%9B%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E8%BF%9B%E7%A8%8B/" class="post-title-link" itemprop="url">python进程</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:15:48" itemprop="dateCreated datePublished" datetime="2020-03-06T14:15:48+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E8%BF%9B%E7%A8%8B/" class="post-meta-item leancloud_visitors" data-flag-title="python进程" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="进程和线程的区别"><a href="#进程和线程的区别" class="headerlink" title="进程和线程的区别"></a>进程和线程的区别</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">import multiprocessing</span><br><span class="line"></span><br><span class="line">def test()</span><br><span class="line">    pass</span><br><span class="line"></span><br><span class="line">p1 &#x3D; multiprocessing.Process(target&#x3D;test)</span><br><span class="line"></span><br><span class="line">p1.start()</span><br></pre></td></tr></table></figure>

<p><strong>进程：</strong></p>
<ol>
<li>程序运行起来就是进程  </li>
<li>是资源分配的单位</li>
<li>进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的执行效率</li>
</ol>
<p><strong>线程：</strong></p>
<ol>
<li>线程是进程中执行具体操作的个体 </li>
<li>是任务调度的单位</li>
<li>线程运行开销小，但不利于资源的管理和保护，进程正相反</li>
<li>线程不能够独立执行，必须依存在进程中</li>
<li>可以将进程理解为工厂中的一条流水线，而其中的线程就是这个流水线上的工人</li>
</ol>
<h4 id="通过队列完成进程间的通信"><a href="#通过队列完成进程间的通信" class="headerlink" title="通过队列完成进程间的通信"></a>通过队列完成进程间的通信</h4><p>队列：先进先出</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">from multiprocessing import Queue</span><br><span class="line"></span><br><span class="line"># 初始化一个Queue对象</span><br><span class="line">q&#x3D;Queue(3)          # 最多可几收三条put信息</span><br><span class="line"></span><br><span class="line"># 往队列中放数据</span><br><span class="line">q.put(&#39;message1&#39;)   # 数据类型任意</span><br><span class="line">q.put(&#39;message2&#39;)</span><br><span class="line">q.put(&#39;message3&#39;)</span><br><span class="line">q.put(&#39;message4&#39;)   # 会阻塞，因为队列满了</span><br><span class="line"></span><br><span class="line"># 判断队列状态</span><br><span class="line">q.full()     # False 表示队列不满</span><br><span class="line">q.full()     # True 表示队列满了</span><br><span class="line">q.empty()    # False 表示队列不为空</span><br><span class="line">q.empty()    # True 表示队列为空</span><br><span class="line"></span><br><span class="line"># 从队列取数据</span><br><span class="line">q.get()             # 先进后出</span><br><span class="line">q.get_nowait()      # 不等待取数据</span><br></pre></td></tr></table></figure>

<p><strong>作用：</strong><br>通过队列解耦合，进程A下载数据，进程B处理数据，互不影响</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">import multiprocessing</span><br><span class="line"></span><br><span class="line">def download_from_web():</span><br><span class="line">    # 模拟从网上下载数据</span><br><span class="line">    data &#x3D;&#x3D; [11, 22, 33, 44]</span><br><span class="line"></span><br><span class="line">    # 像队列中写入数据</span><br><span class="line">    from temp in data:</span><br><span class="line">        q.put()</span><br><span class="line">        </span><br><span class="line">    print(&quot;下载器已经下载完了数据并且存入到队列中。&quot;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def analysis_data():</span><br><span class="line">    &#39;&#39;&#39;数据处理&#39;&#39;&#39;</span><br><span class="line">    waitting_analysis_data &#x3D; list()</span><br><span class="line">    # 从队列中取数据</span><br><span class="line">    while True:</span><br><span class="line">        data &#x3D; q.get()</span><br><span class="line">        waitting_analysis_data.append(data)</span><br><span class="line">        </span><br><span class="line">        if q.empty():</span><br><span class="line">            break</span><br><span class="line"></span><br><span class="line">    # 模拟数据处理</span><br><span class="line">    print(waitting_analysis_data)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main()</span><br><span class="line">    # 1. 创建一个队列</span><br><span class="line">    q &#x3D; multiprocessing.Queue()</span><br><span class="line">    </span><br><span class="line">    # 2. 创建多个进程，将队列的应用当作实参进行传递到里面</span><br><span class="line">    p1 &#x3D; multiprocessing.Process(target&#x3D;download_from_web, args&#x3D;(q,))</span><br><span class="line">    p2 &#x3D; multiprocessing.Process(target&#x3D;analysis_data， argd&#x3D;(q,))</span><br><span class="line"></span><br><span class="line">    p1.start()</span><br><span class="line">    p2.start()</span><br><span class="line">    </span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="进程池Pool"><a href="#进程池Pool" class="headerlink" title="进程池Pool"></a>进程池Pool</h4><p>重复利用进程池中的进程<br>进程数过多时，采用进程池减少进程的数量</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">from multiprocessing import Pool</span><br><span class="line"></span><br><span class="line">po &#x3D; Pool(3)    # 定义一个进程池，最大进程数为3</span><br><span class="line">po.apply_async(worker,(1,))  #要调用的目标，(传递给目标的参数元组,))</span><br><span class="line">po.close()      # 关闭进程池</span><br><span class="line">po.jion()       # 等待po中所有子进程完成，必须放在close()前面</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">from multiprocessing import Pool</span><br><span class="line">import os, time, random</span><br><span class="line"></span><br><span class="line">def worker(msg):</span><br><span class="line">    t_start &#x3D; time.time()</span><br><span class="line">    print(&quot;%s开始执行，进程号为%d&quot; % (msg,os.getpid()))</span><br><span class="line">    # random.random() 随机生成0-1之间的浮点数</span><br><span class="line">    time.sleep(random.random()*2)</span><br><span class="line">    t_stop &#x3D; time.time()</span><br><span class="line">    print(msg,&quot;执行完毕，好事%0.2f&quot; % (t_stop-t_start))</span><br><span class="line">    </span><br><span class="line">po &#x3D; Pool(3)        # 定义一个进程池，最大进程数3</span><br><span class="line">for i in range(0,10):</span><br><span class="line">    # Pool().apply_async(要调用的目标，(传递给目标的参数元组，))</span><br><span class="line">    # 每次循环将会用空闲出来的子进程去调用目标</span><br><span class="line">    po.apply_async(worker,(i,))</span><br><span class="line">    </span><br><span class="line">print(&quot;----start----&quot;)</span><br><span class="line">po.close()          # 关闭进程池，关闭后po不再接收新的请求</span><br><span class="line">po.join()           # 等待po中所有子进程执行完成，必须放在close语句之后</span><br><span class="line">print(&quot;----end----&quot;)</span><br></pre></td></tr></table></figure>

<h4 id="案例-实现copy"><a href="#案例-实现copy" class="headerlink" title="案例 实现copy"></a>案例 实现copy</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">import multiprocessing</span><br><span class="line">import os</span><br><span class="line"></span><br><span class="line">def copy_file(q, file_name, old_folder_name, new_folder_name):</span><br><span class="line">    &#39;&#39;&#39;完成文件的复制&#39;&#39;&#39;</span><br><span class="line">    old_f &#x3D; open(old_folder_name + &quot;&#x2F;&quot; + file_name, &quot;rb&quot;)</span><br><span class="line">    content &#x3D; old_f.read()</span><br><span class="line">    old_f.close()</span><br><span class="line">    </span><br><span class="line">    new_f &#x3D; open(new_folder_name + &quot;&#x2F;&quot; + file_name, &quot;wb&quot;)</span><br><span class="line">    content &#x3D; new_f.write()</span><br><span class="line">    new_f.close()</span><br><span class="line">    </span><br><span class="line">    # 如果拷贝完了文件，那么就向队列中写入一个消息表示已经完成</span><br><span class="line">    q.put(file_name)</span><br><span class="line">    </span><br><span class="line">def main():</span><br><span class="line">    # 1. 获取用户要copy的文件夹的名字</span><br><span class="line">    old_folder_name &#x3D; input(&quot;请输入要copy的文件夹的名字：&quot;)</span><br><span class="line">    </span><br><span class="line">    # 2. 创建一个新的文件夹</span><br><span class="line">    try:</span><br><span class="line">        new_folder_name &#x3D; old_folder_name + &quot;[复件]&quot;</span><br><span class="line">        os.mkdir(new_folder_name)</span><br><span class="line">    except:</span><br><span class="line">        pass</span><br><span class="line"></span><br><span class="line">    # 3. 获取文件夹的所有的待copy的文件名字 listdir()</span><br><span class="line">    file_names &#x3D; os.listdir(old_folder_name)</span><br><span class="line">    # print(file_names)</span><br><span class="line">    </span><br><span class="line">    # 4. 创建进程池 主进程负责往进程池添加 进程池负责拷贝</span><br><span class="line">    po &#x3D; multiprocessing.Pool(5)</span><br><span class="line">    </span><br><span class="line">    # 5. 创建一个队列</span><br><span class="line">    q &#x3D; multiprocessing.Manager().Queue()</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    # 6. 向进程池中添加copy文件的任务</span><br><span class="line">    for file_name in file_names:</span><br><span class="line">        po.apply_async(q, copy_file,args&#x3D;(file_name, old_folder_name. new_folder_name)</span><br><span class="line">    # 进程池中的进程出错时不会抛出异常。</span><br><span class="line">    po.close()</span><br><span class="line">    # po.join()</span><br><span class="line">    all_file_num &#x3D; len(file_names) # 所有文件的个数</span><br><span class="line">    copy_ok_num &#x3D; 0</span><br><span class="line">    while True:</span><br><span class="line">        file_name &#x3D; q.get()</span><br><span class="line">        # print(&quot;已经完成copy： %s&quot; % file_name)</span><br><span class="line">        copy_ok_num +&#x3D; 1</span><br><span class="line">        print(&quot;\r拷贝的进度为：%.2f%%&quot; % (copy_on_num*100 &#x2F;&#x2F; all_file_num),end&#x3D;&quot;&quot;)</span><br><span class="line">        if copy_ok_num &gt;&#x3D; all_file_num:</span><br><span class="line">            break</span><br><span class="line">        </span><br><span class="line">        print()</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E7%BA%BF%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E7%BA%BF%E7%A8%8B/" class="post-title-link" itemprop="url">python线程</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:15:36" itemprop="dateCreated datePublished" datetime="2020-03-06T14:15:36+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E7%BA%BF%E7%A8%8B/" class="post-meta-item leancloud_visitors" data-flag-title="python线程" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="创建多线程"><a href="#创建多线程" class="headerlink" title="创建多线程"></a>创建多线程</h4><ul>
<li><p>demo1</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">import threading</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">def saySorry():</span><br><span class="line">    print(&quot;亲爱的，我错了，我能吃饭了吗？&quot;)</span><br><span class="line">    time.sleep(1)</span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;</span><br><span class="line">    for i in range(5):</span><br><span class="line">        t &#x3D; threading.Thread(target&#x3D;saySorry)  #创建实例对象t</span><br><span class="line">        t.start() #启动线程，生成子线程，运行指定参数</span><br></pre></td></tr></table></figure>
</li>
<li><p>demo2</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br><span class="line">import threading</span><br><span class="line"></span><br><span class="line">def sing():</span><br><span class="line">    &quot;&quot;&quot;唱歌 5秒钟&quot;&quot;&quot;</span><br><span class="line">    for i in range(5):</span><br><span class="line">        print(&quot;---正在唱：菊花茶---&quot;)</span><br><span class="line">        time.sleep(1)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def dance():</span><br><span class="line">    &quot;&quot;&quot;跳舞 5秒钟&quot;&quot;&quot;</span><br><span class="line">    for i in range(5):</span><br><span class="line">        print(&quot;---正在跳舞---&quot;)</span><br><span class="line">        time.sleep(1)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    t1 &#x3D; threading.Thread(target&#x3D;sing)  #创建实例对象t1，传参sing</span><br><span class="line">    t2 &#x3D; threading.Thread(target&#x3D;dance) #创建实例对象t2。传参dance</span><br><span class="line">    t1.start()  #生成子线程</span><br><span class="line">    t2.start()  #生成子线程 </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h4 id="查看线程数量"><a href="#查看线程数量" class="headerlink" title="查看线程数量"></a>查看线程数量</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br><span class="line">import threading</span><br><span class="line"></span><br><span class="line">def test1():</span><br><span class="line">    for i in range(5):</span><br><span class="line">        print(&quot;---test---%d&quot; % i)   #子线程t1</span><br><span class="line">        time.sleep(1)</span><br><span class="line">    #如果创建Thread时执行的函数运行结束，那么意味着这个子线程结束了</span><br><span class="line"></span><br><span class="line">def test2():</span><br><span class="line">    for i in range(10):</span><br><span class="line">        print(&quot;---test---%d&quot; % i)   #子线程t2</span><br><span class="line">        time.sleep(1)</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    t1 &#x3D; threading.Thread(target&#x3D;test1) #创建实例对象t1，传参test1，不创建线程</span><br><span class="line">    t2 &#x3D; threading.Thread(target&#x3D;test2) #创建实例对象t2，传参test2，不创建线程</span><br><span class="line">    </span><br><span class="line">    t1.start()          #生成子线程t1</span><br><span class="line">    t2.start()          #生成子线程t2</span><br><span class="line">    # 线程执行顺序不确定，可通过延时控制执行顺序 </span><br><span class="line">    while True：</span><br><span class="line">        print(threading.enumerate())    #获取当前程序所有线程的信息</span><br><span class="line">        if len(threading,enumerous()) &lt;&#x3D; 1:</span><br><span class="line">            break</span><br><span class="line">        time.sleep(1)</span><br><span class="line">        #主线程结束，程序就会结束，主线程结束会杀掉所有子线程。</span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="通过继承Thread类完成创建线程"><a href="#通过继承Thread类完成创建线程" class="headerlink" title="通过继承Thread类完成创建线程"></a>通过继承Thread类完成创建线程</h4><ul>
<li>demo<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">import threading</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">class MyThread(threading.Thread):       #MyThread类继承自Thread类</span><br><span class="line">    def run(self):                      #方法名必须是run()，才能实现多线程</span><br><span class="line">        for i in range(3):</span><br><span class="line">            time.sleep(3)</span><br><span class="line">            msg &#x3D; &quot;I&#39;m&quot; + self.name + &#39;@&#39; + str(i) #name属性中保存的时当前线程的名字</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">i __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    t &#x3D; MyThread()          #一个实例对象只能开启一个子线程</span><br><span class="line">    t.start()       #start()自动调用子类中的run()方法。</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h4 id="多线程-共享全局变量"><a href="#多线程-共享全局变量" class="headerlink" title="多线程-共享全局变量"></a>多线程-共享全局变量</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import threading</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line"># 定义全局变量</span><br><span class="line">num &#x3D; 100</span><br><span class="line"></span><br><span class="line">def test1():</span><br><span class="line">    global g_num      # 声明该变量是全局变量</span><br><span class="line">    g_num +&#x3D; 1</span><br><span class="line">    print(&quot;in test1 g_num&#x3D;%d&quot; % g_num)</span><br><span class="line"></span><br><span class="line">def test2():</span><br><span class="line">    print(&quot;in test2 g_num&#x3D;%d&quot; % g_num)      #不修改变量是可以不声明直接使用</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    t1 &#x3D; threading.Thread(target&#x3D;test1)</span><br><span class="line">    t2 &#x3D; threading.Thread(target&#x3D;test2)</span><br><span class="line">    </span><br><span class="line">    t1.start()</span><br><span class="line">    time.sleep()</span><br><span class="line">    </span><br><span class="line">    t2.start()</span><br><span class="line">    time.sleep()</span><br><span class="line">    </span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<blockquote>
<p>在一个函数中，对全局变量进行修改的时候，到底是否需要使用global进行说明？</p>
</blockquote>
<p>要看是否对全局变量的执行指向进行了修改，</p>
<p>如果修改了执行，即让全局变量指向了一个新的地方，那么必须使用global，例如test1()</p>
<p>如果仅仅是修改了指向的空间中的数据，此时不需要必须使用global。例如test2()</p>
<h4 id="多线程共享全局变量-args参数"><a href="#多线程共享全局变量-args参数" class="headerlink" title="多线程共享全局变量-args参数"></a>多线程共享全局变量-args参数</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">def test1(temp):</span><br><span class="line">    Null</span><br><span class="line"></span><br><span class="line"># target指定这个线程去哪个函数执行代码</span><br><span class="line"># args指定调用函数的时候传递什么数据过去</span><br><span class="line">t1 &#x3D; threading.Thread(target&#x3D;test1, args&#x3D;(g_num,)) # args传递元组数据类型</span><br></pre></td></tr></table></figure>

<h4 id="多线程-共享全局变量问题"><a href="#多线程-共享全局变量问题" class="headerlink" title="多线程-共享全局变量问题"></a>多线程-共享全局变量问题</h4><h5 id="互斥锁"><a href="#互斥锁" class="headerlink" title="互斥锁"></a>互斥锁</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 创建互斥锁</span><br><span class="line">mutex &#x3D; threading.Lock()    # 同一把锁只能使用一次</span><br><span class="line"></span><br><span class="line"># 锁定</span><br><span class="line">mutex.acquire() # 如果上锁之前已被上锁，则此时阻塞在这里，直至所被解开。</span><br><span class="line"></span><br><span class="line"># 释放</span><br><span class="line">mutex.release()</span><br></pre></td></tr></table></figure>
<p> 银行家算法 死锁预防 超时处理</p>
<h3 id="案例-UDP聊天器"><a href="#案例-UDP聊天器" class="headerlink" title="案例-UDP聊天器"></a>案例-UDP聊天器</h3> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">import socket</span><br><span class="line">import threading</span><br><span class="line"></span><br><span class="line">def recv_msg(udp_socket):</span><br><span class="line">   &#39;&#39;&#39;接受数据并显示&#39;&#39;&#39;</span><br><span class="line">   </span><br><span class="line">   # 接收数据</span><br><span class="line">   while True:</span><br><span class="line">       recv_data &#x3D; udp_socket.recvfrom(1024)</span><br><span class="line">       print(recv_data)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def send_msg(udp_socket, dest_ip, dest_port):</span><br><span class="line">   &#39;&#39;&#39;发送数据&#39;&#39;&#39;</span><br><span class="line">   </span><br><span class="line">   # 发送数据</span><br><span class="line">   while True:</span><br><span class="line">       recv_data &#x3D; input()</span><br><span class="line">       udp_socket.sendto(send_data.encode(&quot;utf-8&quot;). (dest_ip, dest_port))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">   &#39;&#39;&#39;UDP聊天器的整体控制&#39;&#39;&#39;</span><br><span class="line">   </span><br><span class="line">   # 1. 创建套接字</span><br><span class="line">   udp_socket &#x3D; socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line">   </span><br><span class="line">   # 2. 绑定本地信息</span><br><span class="line">   udp_socket.bind(&quot;&quot;,7890)</span><br><span class="line">   </span><br><span class="line">   # 3. 获取对方的IP</span><br><span class="line">   dest_ip &#x3D; input(“请输入对方的IP：”)</span><br><span class="line">   dest_port &#x3D; int(input(&quot;请输入对方的port：&quot;))</span><br><span class="line">   </span><br><span class="line">   # 4. 创建两个线程，执行相应的功能</span><br><span class="line">   t_recv &#x3D; threading.Thread(target&#x3D;recv_msg, args&#x3D;(udp_socket,))</span><br><span class="line">   t_send &#x3D; threading.Thread(target&#x3D;send_msg, args&#x3D;(udp_socket, dest_ip, dest_port))</span><br><span class="line">   </span><br><span class="line">   t_recv.start()</span><br><span class="line">   t_send.start()</span><br><span class="line">   </span><br><span class="line">       </span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">   main()</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

  </div>

  
  <nav class="pagination">
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="CT"
      src="/images/avatar.gif">
  <p class="site-author-name" itemprop="name">CT</p>
  <div class="site-description" itemprop="description">this is a desc.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">16</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">5</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/daydaychen" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;daydaychen" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:ctt0120@foxmail.com" title="E-Mail → mailto:ctt0120@foxmail.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">CT</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v4.2.0
  </div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> v7.7.2
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="//cdn.jsdelivr.net/npm/animejs@3.1.0/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-pjax@0/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/medium-zoom@1/dist/medium-zoom.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/lozad@1/dist/lozad.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/velocity-animate@1/velocity.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/velocity-animate@1/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.getAttribute('pjax') !== null) {
      script.setAttribute('pjax', '');
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="/js/local-search.js"></script>













    <div id="pjax">
  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/valine@1/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : false,
      appId      : '9bBjpz3HRuKNuKNp7T27dFsT-gzGzoHsz',
      appKey     : 'k2pzqGWjkjrKxlFLQ3O0oqDn',
      placeholder: "Just go go",
      avatar     : 'robohash',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : true,
      lang       : 'zh-cn' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

    </div>
</body>
</html>
